blob: 2b04cc50001f5dba59f1bb64ddd6778d2aef9f18 [file] [log] [blame]
// Copyright 2017 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/noscript_preview_page_load_metrics_observer.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/macros.h"
#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "chrome/browser/loader/chrome_navigation_data.h"
#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
#include "chrome/browser/page_load_metrics/page_load_tracker.h"
#include "chrome/common/page_load_metrics/page_load_timing.h"
#include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h"
#include "components/previews/core/previews_features.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/previews_state.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/web_contents_tester.h"
namespace previews {
namespace {
const char kDefaultTestUrl[] = "https://www.google.com";
class NoScriptPreviewPageLoadMetricsObserverTest
: public page_load_metrics::PageLoadMetricsObserverTestHarness {
public:
NoScriptPreviewPageLoadMetricsObserverTest() {}
~NoScriptPreviewPageLoadMetricsObserverTest() override {}
void ResetTest() {
page_load_metrics::InitPageLoadTimingForTest(&timing_);
// Reset to the default testing state. Does not reset histogram state.
timing_.navigation_start = base::Time::FromDoubleT(1);
timing_.response_start = base::TimeDelta::FromSeconds(2);
timing_.parse_timing->parse_start = base::TimeDelta::FromSeconds(3);
timing_.paint_timing->first_contentful_paint =
base::TimeDelta::FromSeconds(4);
timing_.paint_timing->first_paint = base::TimeDelta::FromSeconds(4);
timing_.paint_timing->first_meaningful_paint =
base::TimeDelta::FromSeconds(8);
timing_.paint_timing->first_image_paint = base::TimeDelta::FromSeconds(5);
timing_.paint_timing->first_text_paint = base::TimeDelta::FromSeconds(6);
timing_.document_timing->load_event_start = base::TimeDelta::FromSeconds(7);
timing_.parse_timing->parse_stop = base::TimeDelta::FromSeconds(4);
timing_.parse_timing->parse_blocked_on_script_load_duration =
base::TimeDelta::FromSeconds(1);
PopulateRequiredTimingFields(&timing_);
}
content::GlobalRequestID NavigateAndCommitWithPreviewsState(
content::PreviewsState previews_state) {
auto navigation_simulator =
content::NavigationSimulator::CreateRendererInitiated(
GURL(kDefaultTestUrl), main_rfh());
navigation_simulator->Start();
auto chrome_navigation_data = std::make_unique<ChromeNavigationData>();
chrome_navigation_data->set_previews_state(previews_state);
content::WebContentsTester::For(web_contents())
->SetNavigationData(navigation_simulator->GetNavigationHandle(),
std::move(chrome_navigation_data));
navigation_simulator->Commit();
return navigation_simulator->GetGlobalRequestID();
}
void ValidateTimingHistograms(bool noscript_preview_request_sent) {
ValidateTimingHistogram(noscript_preview_names::kNavigationToLoadEvent,
timing_.document_timing->load_event_start,
noscript_preview_request_sent);
ValidateTimingHistogram(
noscript_preview_names::kNavigationToFirstContentfulPaint,
timing_.paint_timing->first_contentful_paint,
noscript_preview_request_sent);
ValidateTimingHistogram(
noscript_preview_names::kNavigationToFirstMeaningfulPaint,
timing_.paint_timing->first_meaningful_paint,
noscript_preview_request_sent);
ValidateTimingHistogram(
noscript_preview_names::kParseBlockedOnScriptLoad,
timing_.parse_timing->parse_blocked_on_script_load_duration,
noscript_preview_request_sent);
ValidateTimingHistogram(noscript_preview_names::kParseDuration,
timing_.parse_timing->parse_stop.value() -
timing_.parse_timing->parse_start.value(),
noscript_preview_request_sent);
}
void ValidateTimingHistogram(const std::string& histogram,
const base::Optional<base::TimeDelta>& event,
bool noscript_preview_request_sent) {
histogram_tester().ExpectTotalCount(histogram,
noscript_preview_request_sent ? 1 : 0);
if (!noscript_preview_request_sent) {
histogram_tester().ExpectTotalCount(histogram, 0);
} else {
histogram_tester().ExpectUniqueSample(
histogram,
static_cast<base::HistogramBase::Sample>(
event.value().InMilliseconds()),
1);
}
}
void ValidateDataHistograms(int network_resources, int64_t network_bytes) {
if (network_resources > 0) {
histogram_tester().ExpectUniqueSample(
noscript_preview_names::kNumNetworkResources, network_resources, 1);
histogram_tester().ExpectUniqueSample(
noscript_preview_names::kNetworkBytes,
static_cast<int>(network_bytes / 1024), 1);
} else {
histogram_tester().ExpectTotalCount(
noscript_preview_names::kNumNetworkResources, 0);
histogram_tester().ExpectTotalCount(noscript_preview_names::kNetworkBytes,
0);
}
}
protected:
void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
tracker->AddObserver(
std::make_unique<NoScriptPreviewPageLoadMetricsObserver>());
}
page_load_metrics::mojom::PageLoadTiming timing_;
private:
DISALLOW_COPY_AND_ASSIGN(NoScriptPreviewPageLoadMetricsObserverTest);
};
TEST_F(NoScriptPreviewPageLoadMetricsObserverTest, NoScriptPreviewNotSeen) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
previews::features::kNoScriptPreviews);
ResetTest();
content::GlobalRequestID request_id =
NavigateAndCommitWithPreviewsState(content::PREVIEWS_OFF);
page_load_metrics::ExtraRequestCompleteInfo main_frame_info(
GURL(kResourceUrl), net::HostPortPair(), -1 /* frame_tree_node_id */,
false, /* cached */
5 * 1024 /* size */, 0 /* original_network_content_length */,
nullptr
/* data_reduction_proxy_data */,
content::RESOURCE_TYPE_MAIN_FRAME, 0, nullptr /* load_timing_info */);
SimulateLoadedResource(main_frame_info, request_id);
page_load_metrics::ExtraRequestCompleteInfo network_resource_info(
GURL(kResourceUrl), net::HostPortPair(), -1 /* frame_tree_node_id */,
false, /* cached */
20 * 1024 /* size */, 0 /* original_network_content_length */,
nullptr
/* data_reduction_proxy_data */,
content::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */);
SimulateLoadedResource(network_resource_info);
SimulateTimingUpdate(timing_);
NavigateToUntrackedUrl();
ValidateTimingHistograms(false /* is_using_noscript */);
ValidateDataHistograms(0 /* network_resources */, 0 /* network_bytes */);
}
TEST_F(NoScriptPreviewPageLoadMetricsObserverTest, NoScriptPreviewSeen) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
previews::features::kNoScriptPreviews);
ResetTest();
content::GlobalRequestID request_id =
NavigateAndCommitWithPreviewsState(content::NOSCRIPT_ON);
page_load_metrics::ExtraRequestCompleteInfo main_frame_info(
GURL(kResourceUrl), net::HostPortPair(), -1 /* frame_tree_node_id */,
false, /* cached */
5 * 1024 /* size */, 0 /* original_network_content_length */,
nullptr
/* data_reduction_proxy_data */,
content::RESOURCE_TYPE_MAIN_FRAME, 0, nullptr /* load_timing_info */);
SimulateLoadedResource(main_frame_info, request_id);
page_load_metrics::ExtraRequestCompleteInfo cached_resource_info(
GURL(kResourceUrl), net::HostPortPair(), -1 /* frame_tree_node_id */,
true, /* cached */
13 * 1024 /* size */, 0 /* original_network_content_length */,
nullptr
/* data_reduction_proxy_data */,
content::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */);
SimulateLoadedResource(cached_resource_info);
page_load_metrics::ExtraRequestCompleteInfo network_resource_info(
GURL(kResourceUrl), net::HostPortPair(), -1 /* frame_tree_node_id */,
false, /* cached */
20 * 1024 /* size */, 0 /* original_network_content_length */,
nullptr
/* data_reduction_proxy_data */,
content::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */);
SimulateLoadedResource(network_resource_info);
SimulateTimingUpdate(timing_);
NavigateToUntrackedUrl();
ValidateTimingHistograms(true /* is_using_noscript */);
ValidateDataHistograms(2 /* network_resources */,
25 * 1024 /* network_bytes */);
}
} // namespace
} // namespace previews