Commit 30c25549 authored by John Delaney's avatar John Delaney Committed by Commit Bot

Send per-resource updates to PageLoadMetrics

Send data use updates per resource from renderer to browser. This
will allow the browser process to aggregate per-resource information
and will keep feature specific logic out of core PageLoadMetrics
code.

Bug: 873746,851543
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: I34a617c8f1212d9d9ec157de16d65379340b1697
Reviewed-on: https://chromium-review.googlesource.com/1164222
Commit-Queue: John Delaney <johnidel@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarCharlie Harrison <csharrison@chromium.org>
Reviewed-by: default avatarJosh Karlin <jkarlin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583691}
parent 30213c60
...@@ -640,7 +640,8 @@ void MetricsWebContentsObserver::OnTimingUpdated( ...@@ -640,7 +640,8 @@ void MetricsWebContentsObserver::OnTimingUpdated(
const mojom::PageLoadTiming& timing, const mojom::PageLoadTiming& timing,
const mojom::PageLoadMetadata& metadata, const mojom::PageLoadMetadata& metadata,
const mojom::PageLoadFeatures& new_features, const mojom::PageLoadFeatures& new_features,
const mojom::PageLoadDataUse& new_data_use) { const mojom::PageLoadDataUse& new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
// We may receive notifications from frames that have been navigated away // We may receive notifications from frames that have been navigated away
// from. We simply ignore them. // from. We simply ignore them.
if (GetMainFrame(render_frame_host) != web_contents()->GetMainFrame()) { if (GetMainFrame(render_frame_host) != web_contents()->GetMainFrame()) {
...@@ -673,7 +674,8 @@ void MetricsWebContentsObserver::OnTimingUpdated( ...@@ -673,7 +674,8 @@ void MetricsWebContentsObserver::OnTimingUpdated(
if (committed_load_) { if (committed_load_) {
committed_load_->metrics_update_dispatcher()->UpdateMetrics( committed_load_->metrics_update_dispatcher()->UpdateMetrics(
render_frame_host, timing, metadata, new_features, new_data_use); render_frame_host, timing, metadata, new_features, new_data_use,
resources);
} }
} }
...@@ -681,11 +683,12 @@ void MetricsWebContentsObserver::UpdateTiming( ...@@ -681,11 +683,12 @@ void MetricsWebContentsObserver::UpdateTiming(
const mojom::PageLoadTimingPtr timing, const mojom::PageLoadTimingPtr timing,
const mojom::PageLoadMetadataPtr metadata, const mojom::PageLoadMetadataPtr metadata,
const mojom::PageLoadFeaturesPtr new_features, const mojom::PageLoadFeaturesPtr new_features,
const mojom::PageLoadDataUsePtr new_data_use) { const mojom::PageLoadDataUsePtr new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr> resources) {
content::RenderFrameHost* render_frame_host = content::RenderFrameHost* render_frame_host =
page_load_metrics_binding_.GetCurrentTargetFrame(); page_load_metrics_binding_.GetCurrentTargetFrame();
OnTimingUpdated(render_frame_host, *timing, *metadata, *new_features, OnTimingUpdated(render_frame_host, *timing, *metadata, *new_features,
*new_data_use); *new_data_use, resources);
} }
bool MetricsWebContentsObserver::ShouldTrackNavigation( bool MetricsWebContentsObserver::ShouldTrackNavigation(
......
...@@ -146,11 +146,13 @@ class MetricsWebContentsObserver ...@@ -146,11 +146,13 @@ class MetricsWebContentsObserver
void RemoveTestingObserver(TestingObserver* observer); void RemoveTestingObserver(TestingObserver* observer);
// public only for testing // public only for testing
void OnTimingUpdated(content::RenderFrameHost* render_frame_host, void OnTimingUpdated(
const mojom::PageLoadTiming& timing, content::RenderFrameHost* render_frame_host,
const mojom::PageLoadMetadata& metadata, const mojom::PageLoadTiming& timing,
const mojom::PageLoadFeatures& new_features, const mojom::PageLoadMetadata& metadata,
const mojom::PageLoadDataUse& new_data_use); const mojom::PageLoadFeatures& new_features,
const mojom::PageLoadDataUse& new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr>& resources);
// Informs the observers of the currently committed load that the event // Informs the observers of the currently committed load that the event
// corresponding to |event_key| has occurred. This should not be called within // corresponding to |event_key| has occurred. This should not be called within
...@@ -162,10 +164,12 @@ class MetricsWebContentsObserver ...@@ -162,10 +164,12 @@ class MetricsWebContentsObserver
friend class content::WebContentsUserData<MetricsWebContentsObserver>; friend class content::WebContentsUserData<MetricsWebContentsObserver>;
// page_load_metrics::mojom::PageLoadMetrics implementation. // page_load_metrics::mojom::PageLoadMetrics implementation.
void UpdateTiming(const mojom::PageLoadTimingPtr timing, void UpdateTiming(
const mojom::PageLoadMetadataPtr metadata, const mojom::PageLoadTimingPtr timing,
const mojom::PageLoadFeaturesPtr new_features, const mojom::PageLoadMetadataPtr metadata,
const mojom::PageLoadDataUsePtr new_data_use) override; const mojom::PageLoadFeaturesPtr new_features,
const mojom::PageLoadDataUsePtr new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr> resources) override;
void HandleFailedNavigationForTrackedLoad( void HandleFailedNavigationForTrackedLoad(
content::NavigationHandle* navigation_handle, content::NavigationHandle* navigation_handle,
......
...@@ -258,7 +258,8 @@ class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness { ...@@ -258,7 +258,8 @@ class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness {
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
observer()->OnTimingUpdated( observer()->OnTimingUpdated(
render_frame_host, timing, mojom::PageLoadMetadata(), render_frame_host, timing, mojom::PageLoadMetadata(),
mojom::PageLoadFeatures(), mojom::PageLoadDataUse()); mojom::PageLoadFeatures(), mojom::PageLoadDataUse(),
std::vector<mojom::ResourceDataUpdatePtr>());
} }
void AttachObserver() { void AttachObserver() {
......
...@@ -88,7 +88,8 @@ void PageLoadMetricsObserverTester::SimulatePageLoadTimingUpdate( ...@@ -88,7 +88,8 @@ void PageLoadMetricsObserverTester::SimulatePageLoadTimingUpdate(
const mojom::PageLoadMetadata& metadata, const mojom::PageLoadMetadata& metadata,
const mojom::PageLoadFeatures& new_features) { const mojom::PageLoadFeatures& new_features) {
observer_->OnTimingUpdated(web_contents()->GetMainFrame(), timing, metadata, observer_->OnTimingUpdated(web_contents()->GetMainFrame(), timing, metadata,
new_features, mojom::PageLoadDataUse()); new_features, mojom::PageLoadDataUse(),
std::vector<mojom::ResourceDataUpdatePtr>());
// If sending the timing update caused the PageLoadMetricsUpdateDispatcher to // If sending the timing update caused the PageLoadMetricsUpdateDispatcher to
// schedule a buffering timer, then fire it now so metrics are dispatched to // schedule a buffering timer, then fire it now so metrics are dispatched to
// observers. // observers.
...@@ -101,7 +102,8 @@ void PageLoadMetricsObserverTester::SimulatePageLoadDataUseUpdate( ...@@ -101,7 +102,8 @@ void PageLoadMetricsObserverTester::SimulatePageLoadDataUseUpdate(
const mojom::PageLoadDataUse& data_use) { const mojom::PageLoadDataUse& data_use) {
observer_->OnTimingUpdated(web_contents()->GetMainFrame(), observer_->OnTimingUpdated(web_contents()->GetMainFrame(),
mojom::PageLoadTiming(), mojom::PageLoadMetadata(), mojom::PageLoadTiming(), mojom::PageLoadMetadata(),
mojom::PageLoadFeatures(), data_use); mojom::PageLoadFeatures(), data_use,
std::vector<mojom::ResourceDataUpdatePtr>());
} }
void PageLoadMetricsObserverTester::SimulateLoadedResource( void PageLoadMetricsObserverTester::SimulateLoadedResource(
......
...@@ -1852,3 +1852,89 @@ IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ...@@ -1852,3 +1852,89 @@ IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
waiter->AddMinimumPageLoadDataUseExpectation(7 * (one_frame_page_size - 100)); waiter->AddMinimumPageLoadDataUseExpectation(7 * (one_frame_page_size - 100));
waiter->Wait(); waiter->Wait();
} }
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
ReceivedAggregateResourceDataLength) {
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
content::SetupCrossSiteRedirector(embedded_test_server());
ASSERT_TRUE(embedded_test_server()->Start());
auto waiter = CreatePageLoadMetricsTestWaiter();
waiter->AddPageExpectation(TimingField::kLoadEvent);
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL(
"foo.com", "/cross_site_iframe_factory.html?foo"));
waiter->Wait();
int64_t one_frame_page_size = waiter->current_resource_bytes();
waiter = CreatePageLoadMetricsTestWaiter();
waiter->AddPageExpectation(TimingField::kLoadEvent);
ui_test_utils::NavigateToURL(
browser(),
embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b,c,d(e,f,g))"));
// Verify that 7 iframes are fetched, with some amount of tolerance since
// favicon is fetched only once.
waiter->AddMinimumResourceBytesExpectation(7 * (one_frame_page_size - 100));
waiter->Wait();
}
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ReceivedCompleteResources) {
const char kHttpResponseHeader[] =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"\r\n";
auto main_html_response =
std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), "/mock_page.html",
true /*relative_url_is_prefix*/);
auto script_response =
std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), "/script.js",
true /*relative_url_is_prefix*/);
auto iframe_response =
std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), "/iframe.html",
true /*relative_url_is_prefix*/);
ASSERT_TRUE(embedded_test_server()->Start());
auto waiter = CreatePageLoadMetricsTestWaiter();
browser()->OpenURL(content::OpenURLParams(
embedded_test_server()->GetURL("/mock_page.html"), content::Referrer(),
WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
main_html_response->WaitForRequest();
main_html_response->Send(kHttpResponseHeader);
main_html_response->Send(
"<html><body></body><script src=\"script.js\"></script></html>");
main_html_response->Send(std::string(1000, ' '));
main_html_response->Done();
waiter->AddCompleteResourcesExpectation(1);
waiter->AddMinimumResourceBytesExpectation(1000);
waiter->Wait();
script_response->WaitForRequest();
script_response->Send(kHttpResponseHeader);
script_response->Send(
"var iframe = document.createElement(\"iframe\");"
"iframe.src =\"iframe.html\";"
"document.body.appendChild(iframe);");
script_response->Send(std::string(1000, ' '));
// Data received but resource not complete
waiter->AddCompleteResourcesExpectation(1);
waiter->AddMinimumResourceBytesExpectation(2000);
waiter->Wait();
script_response->Done();
waiter->AddCompleteResourcesExpectation(2);
waiter->Wait();
// Make sure main resources are loaded correctly
iframe_response->WaitForRequest();
iframe_response->Send(kHttpResponseHeader);
iframe_response->Send(std::string(2000, ' '));
iframe_response->Done();
waiter->AddCompleteResourcesExpectation(3);
waiter->AddMinimumResourceBytesExpectation(4000);
waiter->Wait();
}
...@@ -428,6 +428,12 @@ class PageLoadMetricsObserver { ...@@ -428,6 +428,12 @@ class PageLoadMetricsObserver {
virtual void OnDataUseObserved(int64_t received_data_length, virtual void OnDataUseObserved(int64_t received_data_length,
int64_t data_reduction_proxy_bytes_saved) {} int64_t data_reduction_proxy_bytes_saved) {}
// Invoked when there is data use for loading a resource on the page
// acrosss all frames. This only contains resources that have had new
// data use since the last callback.
virtual void OnResourceDataUseObserved(
const std::vector<mojom::ResourceDataUpdatePtr>& resources) {}
// Invoked when a media element starts playing. // Invoked when a media element starts playing.
virtual void MediaStartedPlaying( virtual void MediaStartedPlaying(
const content::WebContentsObserver::MediaPlayerInfo& video_type, const content::WebContentsObserver::MediaPlayerInfo& video_type,
......
...@@ -38,6 +38,16 @@ void PageLoadMetricsTestWaiter::AddSubFrameExpectation(TimingField field) { ...@@ -38,6 +38,16 @@ void PageLoadMetricsTestWaiter::AddSubFrameExpectation(TimingField field) {
page_expected_fields_.Set(field); page_expected_fields_.Set(field);
} }
void PageLoadMetricsTestWaiter::AddCompleteResourcesExpectation(
int expected_num_complete_resources) {
expected_num_complete_resources_ = expected_num_complete_resources;
}
void PageLoadMetricsTestWaiter::AddMinimumResourceBytesExpectation(
int expected_minimum_resource_bytes) {
expected_minimum_resource_bytes_ = expected_minimum_resource_bytes;
}
void PageLoadMetricsTestWaiter::AddMinimumPageLoadDataUseExpectation( void PageLoadMetricsTestWaiter::AddMinimumPageLoadDataUseExpectation(
int expected_minimum_page_load_data_use) { int expected_minimum_page_load_data_use) {
expected_minimum_page_load_data_use_ = expected_minimum_page_load_data_use; expected_minimum_page_load_data_use_ = expected_minimum_page_load_data_use;
...@@ -48,21 +58,21 @@ bool PageLoadMetricsTestWaiter::DidObserveInPage(TimingField field) const { ...@@ -48,21 +58,21 @@ bool PageLoadMetricsTestWaiter::DidObserveInPage(TimingField field) const {
} }
void PageLoadMetricsTestWaiter::Wait() { void PageLoadMetricsTestWaiter::Wait() {
if (expectations_satisfied()) if (ExpectationsSatisfied())
return; return;
run_loop_ = std::make_unique<base::RunLoop>(); run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run(); run_loop_->Run();
run_loop_ = nullptr; run_loop_ = nullptr;
EXPECT_TRUE(expectations_satisfied()); EXPECT_TRUE(ExpectationsSatisfied());
} }
void PageLoadMetricsTestWaiter::OnTimingUpdated( void PageLoadMetricsTestWaiter::OnTimingUpdated(
content::RenderFrameHost* subframe_rfh, content::RenderFrameHost* subframe_rfh,
const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::mojom::PageLoadTiming& timing,
const page_load_metrics::PageLoadExtraInfo& extra_info) { const page_load_metrics::PageLoadExtraInfo& extra_info) {
if (expectations_satisfied()) if (ExpectationsSatisfied())
return; return;
const page_load_metrics::mojom::PageLoadMetadata& metadata = const page_load_metrics::mojom::PageLoadMetadata& metadata =
subframe_rfh ? extra_info.subframe_metadata subframe_rfh ? extra_info.subframe_metadata
...@@ -74,14 +84,14 @@ void PageLoadMetricsTestWaiter::OnTimingUpdated( ...@@ -74,14 +84,14 @@ void PageLoadMetricsTestWaiter::OnTimingUpdated(
page_expected_fields_.ClearMatching(matched_bits); page_expected_fields_.ClearMatching(matched_bits);
observed_page_fields_.Merge(matched_bits); observed_page_fields_.Merge(matched_bits);
} }
if (expectations_satisfied() && run_loop_) if (ExpectationsSatisfied() && run_loop_)
run_loop_->Quit(); run_loop_->Quit();
} }
void PageLoadMetricsTestWaiter::OnLoadedResource( void PageLoadMetricsTestWaiter::OnLoadedResource(
const page_load_metrics::ExtraRequestCompleteInfo& const page_load_metrics::ExtraRequestCompleteInfo&
extra_request_complete_info) { extra_request_complete_info) {
if (expectations_satisfied()) if (ExpectationsSatisfied())
return; return;
if (extra_request_complete_info.resource_type != if (extra_request_complete_info.resource_type !=
...@@ -97,7 +107,7 @@ void PageLoadMetricsTestWaiter::OnLoadedResource( ...@@ -97,7 +107,7 @@ void PageLoadMetricsTestWaiter::OnLoadedResource(
observed_page_fields_.Set(TimingField::kLoadTimingInfo); observed_page_fields_.Set(TimingField::kLoadTimingInfo);
} }
if (expectations_satisfied() && run_loop_) if (ExpectationsSatisfied() && run_loop_)
run_loop_->Quit(); run_loop_->Quit();
} }
...@@ -105,7 +115,27 @@ void PageLoadMetricsTestWaiter::OnDataUseObserved( ...@@ -105,7 +115,27 @@ void PageLoadMetricsTestWaiter::OnDataUseObserved(
int64_t received_data_length, int64_t received_data_length,
int64_t data_reduction_proxy_bytes_saved) { int64_t data_reduction_proxy_bytes_saved) {
current_page_load_data_use_ += received_data_length; current_page_load_data_use_ += received_data_length;
if (expectations_satisfied() && run_loop_) if (ExpectationsSatisfied() && run_loop_)
run_loop_->Quit();
}
void PageLoadMetricsTestWaiter::OnResourceDataUseObserved(
const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
resources) {
for (auto const& resource : resources) {
auto it = page_resources_.find(resource->request_id);
if (it != page_resources_.end()) {
it->second = resource.get();
} else {
page_resources_.emplace(std::piecewise_construct,
std::forward_as_tuple(resource->request_id),
std::forward_as_tuple(resource.get()));
}
if (resource->is_complete)
current_complete_resources_++;
current_resource_bytes_ += resource->delta_bytes;
}
if (ExpectationsSatisfied() && run_loop_)
run_loop_->Quit(); run_loop_->Quit();
} }
...@@ -166,12 +196,23 @@ void PageLoadMetricsTestWaiter::OnCommit( ...@@ -166,12 +196,23 @@ void PageLoadMetricsTestWaiter::OnCommit(
did_add_observer_ = true; did_add_observer_ = true;
} }
bool PageLoadMetricsTestWaiter::expectations_satisfied() const { bool PageLoadMetricsTestWaiter::ResourceUseExpectationsSatisfied() const {
return subframe_expected_fields_.Empty() && page_expected_fields_.Empty() && return (expected_num_complete_resources_ == 0 ||
(expected_minimum_page_load_data_use_ == 0 || current_complete_resources_ == expected_num_complete_resources_) &&
(expected_minimum_resource_bytes_ == 0 ||
current_resource_bytes_ >= expected_minimum_resource_bytes_);
}
bool PageLoadMetricsTestWaiter::DataUseExpectationsSatisfied() const {
return (expected_minimum_page_load_data_use_ == 0 ||
current_page_load_data_use_ >= expected_minimum_page_load_data_use_); current_page_load_data_use_ >= expected_minimum_page_load_data_use_);
} }
bool PageLoadMetricsTestWaiter::ExpectationsSatisfied() const {
return subframe_expected_fields_.Empty() && page_expected_fields_.Empty() &&
DataUseExpectationsSatisfied() && ResourceUseExpectationsSatisfied();
}
PageLoadMetricsTestWaiter::WaiterMetricsObserver::~WaiterMetricsObserver() {} PageLoadMetricsTestWaiter::WaiterMetricsObserver::~WaiterMetricsObserver() {}
PageLoadMetricsTestWaiter::WaiterMetricsObserver::WaiterMetricsObserver( PageLoadMetricsTestWaiter::WaiterMetricsObserver::WaiterMetricsObserver(
...@@ -202,4 +243,12 @@ void PageLoadMetricsTestWaiter::WaiterMetricsObserver::OnDataUseObserved( ...@@ -202,4 +243,12 @@ void PageLoadMetricsTestWaiter::WaiterMetricsObserver::OnDataUseObserved(
} }
} }
void PageLoadMetricsTestWaiter::WaiterMetricsObserver::
OnResourceDataUseObserved(
const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
resources) {
if (waiter_)
waiter_->OnResourceDataUseObserved(resources);
}
} // namespace page_load_metrics } // namespace page_load_metrics
...@@ -40,6 +40,12 @@ class PageLoadMetricsTestWaiter ...@@ -40,6 +40,12 @@ class PageLoadMetricsTestWaiter
// Add a subframe-level expectation. // Add a subframe-level expectation.
void AddSubFrameExpectation(TimingField field); void AddSubFrameExpectation(TimingField field);
// Add completed resource expectation
void AddCompleteResourcesExpectation(int expected_minimum_complete_resources);
// Add aggregate received resource bytes expectation
void AddMinimumResourceBytesExpectation(int expected_minimum_resource_bytes);
// Add a data use expectation // Add a data use expectation
void AddMinimumPageLoadDataUseExpectation( void AddMinimumPageLoadDataUseExpectation(
int expected_minimum_page_load_data_use); int expected_minimum_page_load_data_use);
...@@ -56,6 +62,8 @@ class PageLoadMetricsTestWaiter ...@@ -56,6 +62,8 @@ class PageLoadMetricsTestWaiter
return current_page_load_data_use_; return current_page_load_data_use_;
} }
int64_t current_resource_bytes() const { return current_resource_bytes_; }
private: private:
// PageLoadMetricsObserver used by the PageLoadMetricsTestWaiter to observe // PageLoadMetricsObserver used by the PageLoadMetricsTestWaiter to observe
// metrics updates. // metrics updates.
...@@ -79,6 +87,10 @@ class PageLoadMetricsTestWaiter ...@@ -79,6 +87,10 @@ class PageLoadMetricsTestWaiter
void OnDataUseObserved(int64_t received_data_length, void OnDataUseObserved(int64_t received_data_length,
int64_t data_reduction_proxy_bytes_saved) override; int64_t data_reduction_proxy_bytes_saved) override;
void OnResourceDataUseObserved(
const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
resources) override;
private: private:
const base::WeakPtr<PageLoadMetricsTestWaiter> waiter_; const base::WeakPtr<PageLoadMetricsTestWaiter> waiter_;
}; };
...@@ -139,11 +151,22 @@ class PageLoadMetricsTestWaiter ...@@ -139,11 +151,22 @@ class PageLoadMetricsTestWaiter
void OnDataUseObserved(int64_t received_data_length, void OnDataUseObserved(int64_t received_data_length,
int64_t data_reduction_proxy_bytes_saved); int64_t data_reduction_proxy_bytes_saved);
// Updates resource map and associated data counters as updates are received
// from a resource load. Stops waiting if expectations are satisfied after
// update.
void OnResourceDataUseObserved(
const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
resources);
void OnTrackerCreated(page_load_metrics::PageLoadTracker* tracker) override; void OnTrackerCreated(page_load_metrics::PageLoadTracker* tracker) override;
void OnCommit(page_load_metrics::PageLoadTracker* tracker) override; void OnCommit(page_load_metrics::PageLoadTracker* tracker) override;
bool expectations_satisfied() const; bool ResourceUseExpectationsSatisfied() const;
bool DataUseExpectationsSatisfied() const;
virtual bool ExpectationsSatisfied() const;
std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<base::RunLoop> run_loop_;
...@@ -154,10 +177,19 @@ class PageLoadMetricsTestWaiter ...@@ -154,10 +177,19 @@ class PageLoadMetricsTestWaiter
int64_t expected_minimum_page_load_data_use_ = 0; int64_t expected_minimum_page_load_data_use_ = 0;
int64_t current_page_load_data_use_ = 0; int64_t current_page_load_data_use_ = 0;
int current_complete_resources_ = 0;
int64_t current_resource_bytes_ = 0;
int expected_num_complete_resources_ = 0;
int expected_minimum_resource_bytes_ = 0;
bool attach_on_tracker_creation_ = false; bool attach_on_tracker_creation_ = false;
bool did_add_observer_ = false; bool did_add_observer_ = false;
// Map of all resources loaded by the page, keyed by resource request id.
// Contains ongoing and completed resources. Contains only the most recent
// update (version) of the resource.
std::map<int, page_load_metrics::mojom::ResourceDataUpdate*> page_resources_;
base::WeakPtrFactory<PageLoadMetricsTestWaiter> weak_factory_; base::WeakPtrFactory<PageLoadMetricsTestWaiter> weak_factory_;
}; };
......
...@@ -431,7 +431,8 @@ void PageLoadMetricsUpdateDispatcher::UpdateMetrics( ...@@ -431,7 +431,8 @@ void PageLoadMetricsUpdateDispatcher::UpdateMetrics(
const mojom::PageLoadTiming& new_timing, const mojom::PageLoadTiming& new_timing,
const mojom::PageLoadMetadata& new_metadata, const mojom::PageLoadMetadata& new_metadata,
const mojom::PageLoadFeatures& new_features, const mojom::PageLoadFeatures& new_features,
const mojom::PageLoadDataUse& new_data_use) { const mojom::PageLoadDataUse& new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
if (render_frame_host->GetLastCommittedURL().SchemeIs( if (render_frame_host->GetLastCommittedURL().SchemeIs(
extensions::kExtensionScheme)) { extensions::kExtensionScheme)) {
// Extensions can inject child frames into a page. We don't want to track // Extensions can inject child frames into a page. We don't want to track
...@@ -442,6 +443,7 @@ void PageLoadMetricsUpdateDispatcher::UpdateMetrics( ...@@ -442,6 +443,7 @@ void PageLoadMetricsUpdateDispatcher::UpdateMetrics(
// Report data usage before new timing and metadata for messages that have // Report data usage before new timing and metadata for messages that have
// both updates. // both updates.
client_->UpdateDataUse(new_data_use); client_->UpdateDataUse(new_data_use);
client_->UpdateResourceDataUse(resources);
if (render_frame_host->GetParent() == nullptr) { if (render_frame_host->GetParent() == nullptr) {
UpdateMainFrameMetadata(new_metadata); UpdateMainFrameMetadata(new_metadata);
UpdateMainFrameTiming(new_timing); UpdateMainFrameTiming(new_timing);
......
...@@ -110,6 +110,8 @@ class PageLoadMetricsUpdateDispatcher { ...@@ -110,6 +110,8 @@ class PageLoadMetricsUpdateDispatcher {
virtual void UpdateFeaturesUsage( virtual void UpdateFeaturesUsage(
const mojom::PageLoadFeatures& new_features) = 0; const mojom::PageLoadFeatures& new_features) = 0;
virtual void UpdateDataUse(const mojom::PageLoadDataUse& new_data_use) = 0; virtual void UpdateDataUse(const mojom::PageLoadDataUse& new_data_use) = 0;
virtual void UpdateResourceDataUse(
const std::vector<mojom::ResourceDataUpdatePtr>& resources) = 0;
}; };
// The |client| instance must outlive this object. // The |client| instance must outlive this object.
...@@ -119,11 +121,13 @@ class PageLoadMetricsUpdateDispatcher { ...@@ -119,11 +121,13 @@ class PageLoadMetricsUpdateDispatcher {
PageLoadMetricsEmbedderInterface* embedder_interface); PageLoadMetricsEmbedderInterface* embedder_interface);
~PageLoadMetricsUpdateDispatcher(); ~PageLoadMetricsUpdateDispatcher();
void UpdateMetrics(content::RenderFrameHost* render_frame_host, void UpdateMetrics(
const mojom::PageLoadTiming& new_timing, content::RenderFrameHost* render_frame_host,
const mojom::PageLoadMetadata& new_metadata, const mojom::PageLoadTiming& new_timing,
const mojom::PageLoadFeatures& new_features, const mojom::PageLoadMetadata& new_metadata,
const mojom::PageLoadDataUse& new_data_use); const mojom::PageLoadFeatures& new_features,
const mojom::PageLoadDataUse& new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr>& resources);
// This method is only intended to be called for PageLoadFeatures being // This method is only intended to be called for PageLoadFeatures being
// recorded directly from the browser process. Features coming from the // recorded directly from the browser process. Features coming from the
......
...@@ -651,4 +651,11 @@ void PageLoadTracker::UpdateDataUse( ...@@ -651,4 +651,11 @@ void PageLoadTracker::UpdateDataUse(
} }
} }
void PageLoadTracker::UpdateResourceDataUse(
const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
for (const auto& observer : observers_) {
observer->OnResourceDataUseObserved(resources);
}
}
} // namespace page_load_metrics } // namespace page_load_metrics
...@@ -181,6 +181,8 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client { ...@@ -181,6 +181,8 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client {
void UpdateFeaturesUsage( void UpdateFeaturesUsage(
const mojom::PageLoadFeatures& new_features) override; const mojom::PageLoadFeatures& new_features) override;
void UpdateDataUse(const mojom::PageLoadDataUse& new_datause) override; void UpdateDataUse(const mojom::PageLoadDataUse& new_datause) override;
void UpdateResourceDataUse(
const std::vector<mojom::ResourceDataUpdatePtr>& resources) override;
void Redirect(content::NavigationHandle* navigation_handle); void Redirect(content::NavigationHandle* navigation_handle);
void WillProcessNavigationResponse( void WillProcessNavigationResponse(
......
...@@ -152,6 +152,8 @@ struct PageLoadFeatures { ...@@ -152,6 +152,8 @@ struct PageLoadFeatures {
}; };
// Data used for the page load. // Data used for the page load.
// TODO(johnidel): Remove/deprecate this struct once per resource updates are
// being sent to the browser
struct PageLoadDataUse { struct PageLoadDataUse {
// Network bytes received for the page load. // Network bytes received for the page load.
int64 received_data_length = 0; int64 received_data_length = 0;
...@@ -162,11 +164,28 @@ struct PageLoadDataUse { ...@@ -162,11 +164,28 @@ struct PageLoadDataUse {
int64 data_reduction_proxy_bytes_saved = 0; int64 data_reduction_proxy_bytes_saved = 0;
}; };
struct ResourceDataUpdate {
// The id for the resource request.
int32 request_id = 0;
// Network bytes received for the resource since the last timing update
// from renderer to browser.
int64 delta_bytes = 0;
// Total network bytes received for the resource across timing updates. This
// is the aggregate of the |delta_bytes| from each timing update.
int64 received_data_length = 0;
// Whether this resource load has completed.
bool is_complete;
};
// Sent from renderer to browser process when the PageLoadTiming for the // Sent from renderer to browser process when the PageLoadTiming for the
// associated frame changed. // associated frame changed.
interface PageLoadMetrics { interface PageLoadMetrics {
UpdateTiming(PageLoadTiming page_load_timing, UpdateTiming(PageLoadTiming page_load_timing,
PageLoadMetadata page_load_metadata, PageLoadMetadata page_load_metadata,
PageLoadFeatures new_features, PageLoadFeatures new_features,
PageLoadDataUse data_use); PageLoadDataUse data_use,
array<ResourceDataUpdate> resources);
}; };
...@@ -18,8 +18,10 @@ void FakePageTimingSender::SendTiming( ...@@ -18,8 +18,10 @@ void FakePageTimingSender::SendTiming(
const mojom::PageLoadTimingPtr& timing, const mojom::PageLoadTimingPtr& timing,
const mojom::PageLoadMetadataPtr& metadata, const mojom::PageLoadMetadataPtr& metadata,
mojom::PageLoadFeaturesPtr new_features, mojom::PageLoadFeaturesPtr new_features,
mojom::PageLoadDataUsePtr new_data_use) { mojom::PageLoadDataUsePtr new_data_use,
validator_->UpdateTiming(timing, metadata, new_features, new_data_use); std::vector<mojom::ResourceDataUpdatePtr> resources) {
validator_->UpdateTiming(timing, metadata, new_features, new_data_use,
resources);
} }
FakePageTimingSender::PageTimingValidator::PageTimingValidator() {} FakePageTimingSender::PageTimingValidator::PageTimingValidator() {}
...@@ -95,7 +97,8 @@ void FakePageTimingSender::PageTimingValidator::UpdateTiming( ...@@ -95,7 +97,8 @@ void FakePageTimingSender::PageTimingValidator::UpdateTiming(
const mojom::PageLoadTimingPtr& timing, const mojom::PageLoadTimingPtr& timing,
const mojom::PageLoadMetadataPtr& metadata, const mojom::PageLoadMetadataPtr& metadata,
const mojom::PageLoadFeaturesPtr& new_features, const mojom::PageLoadFeaturesPtr& new_features,
const mojom::PageLoadDataUsePtr& new_data_use) { const mojom::PageLoadDataUsePtr& new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
actual_timings_.push_back(timing.Clone()); actual_timings_.push_back(timing.Clone());
for (const auto feature : new_features->features) { for (const auto feature : new_features->features) {
EXPECT_EQ(actual_features_.find(feature), actual_features_.end()) EXPECT_EQ(actual_features_.find(feature), actual_features_.end())
......
...@@ -68,10 +68,12 @@ class FakePageTimingSender : public PageTimingSender { ...@@ -68,10 +68,12 @@ class FakePageTimingSender : public PageTimingSender {
return actual_timings_; return actual_timings_;
} }
void UpdateTiming(const mojom::PageLoadTimingPtr& timing, void UpdateTiming(
const mojom::PageLoadMetadataPtr& metadata, const mojom::PageLoadTimingPtr& timing,
const mojom::PageLoadFeaturesPtr& new_features, const mojom::PageLoadMetadataPtr& metadata,
const mojom::PageLoadDataUsePtr& new_data_use); const mojom::PageLoadFeaturesPtr& new_features,
const mojom::PageLoadDataUsePtr& new_data_use,
const std::vector<mojom::ResourceDataUpdatePtr>& resources);
private: private:
std::vector<mojom::PageLoadTimingPtr> expected_timings_; std::vector<mojom::PageLoadTimingPtr> expected_timings_;
...@@ -88,7 +90,8 @@ class FakePageTimingSender : public PageTimingSender { ...@@ -88,7 +90,8 @@ class FakePageTimingSender : public PageTimingSender {
void SendTiming(const mojom::PageLoadTimingPtr& timing, void SendTiming(const mojom::PageLoadTimingPtr& timing,
const mojom::PageLoadMetadataPtr& metadata, const mojom::PageLoadMetadataPtr& metadata,
mojom::PageLoadFeaturesPtr new_features, mojom::PageLoadFeaturesPtr new_features,
mojom::PageLoadDataUsePtr new_data_use) override; mojom::PageLoadDataUsePtr new_data_use,
std::vector<mojom::ResourceDataUpdatePtr> resources) override;
private: private:
PageTimingValidator* const validator_; PageTimingValidator* const validator_;
......
...@@ -38,14 +38,16 @@ class MojoPageTimingSender : public PageTimingSender { ...@@ -38,14 +38,16 @@ class MojoPageTimingSender : public PageTimingSender {
&page_load_metrics_); &page_load_metrics_);
} }
~MojoPageTimingSender() override {} ~MojoPageTimingSender() override {}
void SendTiming(const mojom::PageLoadTimingPtr& timing, void SendTiming(
const mojom::PageLoadMetadataPtr& metadata, const mojom::PageLoadTimingPtr& timing,
mojom::PageLoadFeaturesPtr new_features, const mojom::PageLoadMetadataPtr& metadata,
mojom::PageLoadDataUsePtr new_data_use) override { mojom::PageLoadFeaturesPtr new_features,
mojom::PageLoadDataUsePtr new_data_use,
std::vector<mojom::ResourceDataUpdatePtr> resources) override {
DCHECK(page_load_metrics_); DCHECK(page_load_metrics_);
page_load_metrics_->UpdateTiming(timing->Clone(), metadata->Clone(), page_load_metrics_->UpdateTiming(
std::move(new_features), timing->Clone(), metadata->Clone(), std::move(new_features),
std::move(new_data_use)); std::move(new_data_use), std::move(resources));
} }
private: private:
......
...@@ -14,7 +14,10 @@ namespace page_load_metrics { ...@@ -14,7 +14,10 @@ namespace page_load_metrics {
PageResourceDataUse::PageResourceDataUse() PageResourceDataUse::PageResourceDataUse()
: resource_id_(-1), : resource_id_(-1),
data_reduction_proxy_compression_ratio_estimate_(1.0), data_reduction_proxy_compression_ratio_estimate_(1.0),
total_received_bytes_(0) {} total_received_bytes_(0),
last_update_bytes_(0),
is_complete_(false),
is_canceled_(false) {}
PageResourceDataUse::~PageResourceDataUse() = default; PageResourceDataUse::~PageResourceDataUse() = default;
...@@ -25,6 +28,7 @@ void PageResourceDataUse::DidStartResponse( ...@@ -25,6 +28,7 @@ void PageResourceDataUse::DidStartResponse(
data_reduction_proxy_compression_ratio_estimate_ = data_reduction_proxy_compression_ratio_estimate_ =
data_reduction_proxy::EstimateCompressionRatioFromHeaders(&response_head); data_reduction_proxy::EstimateCompressionRatioFromHeaders(&response_head);
total_received_bytes_ = 0; total_received_bytes_ = 0;
last_update_bytes_ = 0;
} }
void PageResourceDataUse::DidReceiveTransferSizeUpdate( void PageResourceDataUse::DidReceiveTransferSizeUpdate(
...@@ -41,8 +45,10 @@ bool PageResourceDataUse::DidCompleteResponse( ...@@ -41,8 +45,10 @@ bool PageResourceDataUse::DidCompleteResponse(
const network::URLLoaderCompletionStatus& status, const network::URLLoaderCompletionStatus& status,
mojom::PageLoadDataUse* delta_data_use) { mojom::PageLoadDataUse* delta_data_use) {
// Report the difference in received bytes. // Report the difference in received bytes.
is_complete_ = true;
int64_t delta_bytes = status.encoded_data_length - total_received_bytes_; int64_t delta_bytes = status.encoded_data_length - total_received_bytes_;
if (delta_bytes > 0) { if (delta_bytes > 0) {
total_received_bytes_ += delta_bytes;
delta_data_use->received_data_length += delta_bytes; delta_data_use->received_data_length += delta_bytes;
delta_data_use->data_reduction_proxy_bytes_saved += delta_data_use->data_reduction_proxy_bytes_saved +=
delta_bytes * (data_reduction_proxy_compression_ratio_estimate_ - 1.0); delta_bytes * (data_reduction_proxy_compression_ratio_estimate_ - 1.0);
...@@ -51,4 +57,28 @@ bool PageResourceDataUse::DidCompleteResponse( ...@@ -51,4 +57,28 @@ bool PageResourceDataUse::DidCompleteResponse(
return false; return false;
} }
void PageResourceDataUse::DidCancelResponse() {
is_canceled_ = true;
}
bool PageResourceDataUse::IsFinishedLoading() {
return is_complete_ || is_canceled_;
}
int PageResourceDataUse::CalculateNewlyReceivedBytes() {
int newly_received_bytes = total_received_bytes_ - last_update_bytes_;
last_update_bytes_ = total_received_bytes_;
DCHECK(newly_received_bytes >= 0);
return newly_received_bytes;
}
mojom::ResourceDataUpdatePtr PageResourceDataUse::GetResourceDataUpdate() {
mojom::ResourceDataUpdatePtr resource_data_update =
mojom::ResourceDataUpdate::New();
resource_data_update->request_id = resource_id();
resource_data_update->received_data_length = total_received_bytes_;
resource_data_update->delta_bytes = CalculateNewlyReceivedBytes();
resource_data_update->is_complete = is_complete_;
return resource_data_update;
}
} // namespace page_load_metrics } // namespace page_load_metrics
...@@ -34,9 +34,25 @@ class PageResourceDataUse { ...@@ -34,9 +34,25 @@ class PageResourceDataUse {
bool DidCompleteResponse(const network::URLLoaderCompletionStatus& status, bool DidCompleteResponse(const network::URLLoaderCompletionStatus& status,
mojom::PageLoadDataUse* delta_data_use); mojom::PageLoadDataUse* delta_data_use);
// Flags the resource as canceled.
void DidCancelResponse();
// Checks if the resource has completed loading or if the response was
// cancelled.
bool IsFinishedLoading();
int resource_id() const { return resource_id_; } int resource_id() const { return resource_id_; }
// Creates a ResourceDataUpdate mojo for this resource. This page resource
// contains information since the last time update. Should be called at most
// once once per timing update.
mojom::ResourceDataUpdatePtr GetResourceDataUpdate();
private: private:
// Calculates the difference between |total_received_bytes_| and
// |last_update_bytes_|, returns it, and updates |last_update_bytes_|.
int CalculateNewlyReceivedBytes();
int resource_id_; int resource_id_;
// Compression ratio estimated from the response headers if data saver was // Compression ratio estimated from the response headers if data saver was
...@@ -44,6 +60,10 @@ class PageResourceDataUse { ...@@ -44,6 +60,10 @@ class PageResourceDataUse {
double data_reduction_proxy_compression_ratio_estimate_; double data_reduction_proxy_compression_ratio_estimate_;
uint64_t total_received_bytes_; uint64_t total_received_bytes_;
uint64_t last_update_bytes_;
bool is_complete_;
bool is_canceled_;
DISALLOW_ASSIGN(PageResourceDataUse); DISALLOW_ASSIGN(PageResourceDataUse);
}; };
......
...@@ -61,8 +61,9 @@ PageTimingMetricsSender::~PageTimingMetricsSender() { ...@@ -61,8 +61,9 @@ PageTimingMetricsSender::~PageTimingMetricsSender() {
void PageTimingMetricsSender::DidObserveLoadingBehavior( void PageTimingMetricsSender::DidObserveLoadingBehavior(
blink::WebLoadingBehaviorFlag behavior) { blink::WebLoadingBehaviorFlag behavior) {
if (behavior & metadata_->behavior_flags) if (behavior & metadata_->behavior_flags) {
return; return;
}
metadata_->behavior_flags |= behavior; metadata_->behavior_flags |= behavior;
EnsureSendTimer(); EnsureSendTimer();
} }
...@@ -70,8 +71,9 @@ void PageTimingMetricsSender::DidObserveLoadingBehavior( ...@@ -70,8 +71,9 @@ void PageTimingMetricsSender::DidObserveLoadingBehavior(
void PageTimingMetricsSender::DidObserveNewFeatureUsage( void PageTimingMetricsSender::DidObserveNewFeatureUsage(
blink::mojom::WebFeature feature) { blink::mojom::WebFeature feature) {
int32_t feature_id = static_cast<int32_t>(feature); int32_t feature_id = static_cast<int32_t>(feature);
if (features_sent_.test(feature_id)) if (features_sent_.test(feature_id)) {
return; return;
}
features_sent_.set(feature_id); features_sent_.set(feature_id);
new_features_->features.push_back(feature); new_features_->features.push_back(feature);
EnsureSendTimer(); EnsureSendTimer();
...@@ -109,11 +111,13 @@ void PageTimingMetricsSender::DidReceiveTransferSizeUpdate( ...@@ -109,11 +111,13 @@ void PageTimingMetricsSender::DidReceiveTransferSizeUpdate(
// It is possible that resources are not in the map, if response headers were // It is possible that resources are not in the map, if response headers were
// not received or for failed/cancelled resources. // not received or for failed/cancelled resources.
if (resource_it == page_resource_data_use_.end()) if (resource_it == page_resource_data_use_.end()) {
return; return;
}
resource_it->second.DidReceiveTransferSizeUpdate(received_data_length, resource_it->second.DidReceiveTransferSizeUpdate(received_data_length,
new_data_use_.get()); new_data_use_.get());
modified_resources_.insert(&resource_it->second);
EnsureSendTimer(); EnsureSendTimer();
} }
...@@ -132,17 +136,24 @@ void PageTimingMetricsSender::DidCompleteResponse( ...@@ -132,17 +136,24 @@ void PageTimingMetricsSender::DidCompleteResponse(
resource_it = new_resource_it.first; resource_it = new_resource_it.first;
} }
if (resource_it->second.DidCompleteResponse(status, new_data_use_.get())) if (resource_it->second.DidCompleteResponse(status, new_data_use_.get())) {
EnsureSendTimer(); EnsureSendTimer();
}
modified_resources_.insert(&resource_it->second);
} }
void PageTimingMetricsSender::DidCancelResponse(int resource_id) { void PageTimingMetricsSender::DidCancelResponse(int resource_id) {
page_resource_data_use_.erase(resource_id); auto resource_it = page_resource_data_use_.find(resource_id);
if (resource_it == page_resource_data_use_.end()) {
return;
}
resource_it->second.DidCancelResponse();
} }
void PageTimingMetricsSender::Send(mojom::PageLoadTimingPtr timing) { void PageTimingMetricsSender::Send(mojom::PageLoadTimingPtr timing) {
if (last_timing_->Equals(*timing)) if (last_timing_->Equals(*timing)) {
return; return;
}
// We want to make sure that each PageTimingMetricsSender is associated // We want to make sure that each PageTimingMetricsSender is associated
// with a distinct page navigation. Because we reset the object on commit, // with a distinct page navigation. Because we reset the object on commit,
...@@ -170,10 +181,18 @@ void PageTimingMetricsSender::EnsureSendTimer() { ...@@ -170,10 +181,18 @@ void PageTimingMetricsSender::EnsureSendTimer() {
void PageTimingMetricsSender::SendNow() { void PageTimingMetricsSender::SendNow() {
have_sent_ipc_ = true; have_sent_ipc_ = true;
std::vector<mojom::ResourceDataUpdatePtr> resources;
for (auto* resource : modified_resources_) {
resources.push_back(resource->GetResourceDataUpdate());
if (resource->IsFinishedLoading()) {
page_resource_data_use_.erase(resource->resource_id());
}
}
sender_->SendTiming(last_timing_, metadata_, std::move(new_features_), sender_->SendTiming(last_timing_, metadata_, std::move(new_features_),
std::move(new_data_use_)); std::move(new_data_use_), std::move(resources));
new_features_ = mojom::PageLoadFeatures::New(); new_features_ = mojom::PageLoadFeatures::New();
new_data_use_ = mojom::PageLoadDataUse::New(); new_data_use_ = mojom::PageLoadDataUse::New();
modified_resources_.clear();
} }
} // namespace page_load_metrics } // namespace page_load_metrics
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <bitset> #include <bitset>
#include <memory> #include <memory>
#include "base/containers/flat_set.h"
#include "base/containers/small_map.h" #include "base/containers/small_map.h"
#include "base/macros.h" #include "base/macros.h"
#include "chrome/common/page_load_metrics/page_load_timing.h" #include "chrome/common/page_load_metrics/page_load_timing.h"
...@@ -83,9 +84,15 @@ class PageTimingMetricsSender { ...@@ -83,9 +84,15 @@ class PageTimingMetricsSender {
bool have_sent_ipc_ = false; bool have_sent_ipc_ = false;
// The page's resources that are currently loading, or were completed after
// the last timing update.
base::small_map<std::map<int, PageResourceDataUse>, 16> base::small_map<std::map<int, PageResourceDataUse>, 16>
page_resource_data_use_; page_resource_data_use_;
// Set of all resources that have completed or received a transfer
// size update since the last timimg update.
base::flat_set<PageResourceDataUse*> modified_resources_;
// Field trial for alternating page timing metrics sender buffer timer delay. // Field trial for alternating page timing metrics sender buffer timer delay.
// https://crbug.com/847269. // https://crbug.com/847269.
int buffer_timer_delay_ms_; int buffer_timer_delay_ms_;
......
...@@ -14,10 +14,12 @@ namespace page_load_metrics { ...@@ -14,10 +14,12 @@ namespace page_load_metrics {
class PageTimingSender { class PageTimingSender {
public: public:
virtual ~PageTimingSender() {} virtual ~PageTimingSender() {}
virtual void SendTiming(const mojom::PageLoadTimingPtr& timing, virtual void SendTiming(
const mojom::PageLoadMetadataPtr& metadata, const mojom::PageLoadTimingPtr& timing,
mojom::PageLoadFeaturesPtr new_features, const mojom::PageLoadMetadataPtr& metadata,
mojom::PageLoadDataUsePtr new_data_use) = 0; mojom::PageLoadFeaturesPtr new_features,
mojom::PageLoadDataUsePtr new_data_use,
std::vector<mojom::ResourceDataUpdatePtr> resources) = 0;
}; };
} // namespace page_load_metrics } // namespace page_load_metrics
......
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
# https://crbug.com/816684 Track Page Load Metrics. # https://crbug.com/816684 Track Page Load Metrics.
-PageLoadMetricsBrowserTest.LoadingMetricsFailed -PageLoadMetricsBrowserTest.LoadingMetricsFailed
-PageLoadMetricsBrowserTest.ReceivedCompleteResources
# https://crbug.com/810329 DnsProbe browsertests that rely on delaying requests: # https://crbug.com/810329 DnsProbe browsertests that rely on delaying requests:
-DnsProbeBrowserTest.NxdomainProbeResultWithWorkingSlowCorrections -DnsProbeBrowserTest.NxdomainProbeResultWithWorkingSlowCorrections
......
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