| // Copyright 2016 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/document_write_page_load_metrics_observer.h" |
| |
| #include <memory> |
| |
| #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h" |
| #include "chrome/test/base/testing_browser_process.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 "services/metrics/public/cpp/ukm_builders.h" |
| #include "third_party/blink/public/platform/web_loading_behavior_flag.h" |
| |
| class DocumentWritePageLoadMetricsObserverTest |
| : public page_load_metrics::PageLoadMetricsObserverTestHarness { |
| protected: |
| void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override { |
| tracker->AddObserver( |
| std::make_unique<DocumentWritePageLoadMetricsObserver>()); |
| } |
| |
| void AssertNoBlockHistogramsLogged() { |
| histogram_tester().ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0); |
| } |
| }; |
| |
| TEST_F(DocumentWritePageLoadMetricsObserverTest, NoMetrics) { |
| AssertNoBlockHistogramsLogged(); |
| EXPECT_EQ(0ul, test_ukm_recorder().entries_count()); |
| } |
| |
| TEST_F(DocumentWritePageLoadMetricsObserverTest, PossibleBlock) { |
| base::TimeDelta contentful_paint = base::TimeDelta::FromMilliseconds(1); |
| page_load_metrics::mojom::PageLoadTiming timing; |
| page_load_metrics::InitPageLoadTimingForTest(&timing); |
| timing.navigation_start = base::Time::FromDoubleT(1); |
| timing.paint_timing->first_contentful_paint = contentful_paint; |
| timing.parse_timing->parse_start = base::TimeDelta::FromMilliseconds(1); |
| timing.parse_timing->parse_stop = base::TimeDelta::FromMilliseconds(100); |
| timing.parse_timing->parse_blocked_on_script_load_duration = |
| base::TimeDelta::FromMilliseconds(5); |
| timing.parse_timing |
| ->parse_blocked_on_script_load_from_document_write_duration = |
| base::TimeDelta::FromMilliseconds(5); |
| timing.parse_timing->parse_blocked_on_script_execution_duration = |
| base::TimeDelta::FromMilliseconds(3); |
| timing.parse_timing |
| ->parse_blocked_on_script_execution_from_document_write_duration = |
| base::TimeDelta::FromMilliseconds(3); |
| PopulateRequiredTimingFields(&timing); |
| |
| page_load_metrics::mojom::PageLoadMetadata metadata; |
| metadata.behavior_flags |= |
| blink::WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlock; |
| NavigateAndCommit(GURL("https://www.google.com/")); |
| SimulateTimingAndMetadataUpdate(timing, metadata); |
| |
| histogram_tester().ExpectTotalCount(internal::kHistogramDocWriteBlockCount, |
| 1); |
| histogram_tester().ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
| histogram_tester().ExpectBucketCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, |
| contentful_paint.InMilliseconds(), 1); |
| |
| using Entry = ukm::builders::Intervention_DocumentWrite_ScriptBlock; |
| |
| std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> entries = |
| test_ukm_recorder().GetMergedEntriesByName(Entry::kEntryName); |
| EXPECT_EQ(1u, entries.size()); |
| for (const auto& kv : entries) { |
| test_ukm_recorder().ExpectEntrySourceHasUrl( |
| kv.second.get(), GURL("https://www.google.com/")); |
| test_ukm_recorder().ExpectEntryMetric( |
| kv.second.get(), |
| Entry::kParseTiming_ParseBlockedOnScriptLoadFromDocumentWriteName, 5); |
| test_ukm_recorder().ExpectEntryMetric( |
| kv.second.get(), |
| Entry::kParseTiming_ParseBlockedOnScriptExecutionFromDocumentWriteName, |
| 3); |
| } |
| |
| NavigateAndCommit(GURL("https://www.example.com/")); |
| |
| histogram_tester().ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
| histogram_tester().ExpectBucketCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, |
| contentful_paint.InMilliseconds(), 1); |
| } |
| |
| TEST_F(DocumentWritePageLoadMetricsObserverTest, PossibleBlockReload) { |
| base::TimeDelta contentful_paint = base::TimeDelta::FromMilliseconds(1); |
| page_load_metrics::mojom::PageLoadTiming timing; |
| page_load_metrics::InitPageLoadTimingForTest(&timing); |
| timing.navigation_start = base::Time::FromDoubleT(1); |
| timing.paint_timing->first_contentful_paint = contentful_paint; |
| timing.parse_timing->parse_start = base::TimeDelta::FromMilliseconds(1); |
| PopulateRequiredTimingFields(&timing); |
| |
| page_load_metrics::mojom::PageLoadMetadata metadata; |
| metadata.behavior_flags |= blink::WebLoadingBehaviorFlag:: |
| kWebLoadingBehaviorDocumentWriteBlockReload; |
| NavigateAndCommit(GURL("https://www.google.com/")); |
| SimulateTimingAndMetadataUpdate(timing, metadata); |
| |
| histogram_tester().ExpectTotalCount( |
| internal::kHistogramDocWriteBlockReloadCount, 1); |
| |
| using Entry = ukm::builders::Intervention_DocumentWrite_ScriptBlock; |
| auto entries = test_ukm_recorder().GetEntriesByName(Entry::kEntryName); |
| EXPECT_EQ(1u, entries.size()); |
| const ukm::mojom::UkmEntry* entry1 = nullptr; |
| for (const auto* const entry : entries) { |
| test_ukm_recorder().ExpectEntrySourceHasUrl( |
| entry, GURL("https://www.google.com/")); |
| test_ukm_recorder().ExpectEntryMetric(entry, Entry::kDisabled_ReloadName, |
| true); |
| entry1 = entry; |
| } |
| |
| // Another reload. |
| NavigateAndCommit(GURL("https://www.example.com/")); |
| SimulateTimingAndMetadataUpdate(timing, metadata); |
| |
| histogram_tester().ExpectTotalCount( |
| internal::kHistogramDocWriteBlockReloadCount, 2); |
| |
| auto entries2 = test_ukm_recorder().GetEntriesByName(Entry::kEntryName); |
| EXPECT_EQ(2u, entries2.size()); |
| for (const auto* const entry : entries2) { |
| if (entry != entry1) |
| test_ukm_recorder().ExpectEntrySourceHasUrl( |
| entry, GURL("https://www.example.com/")); |
| test_ukm_recorder().ExpectEntryMetric(entry, Entry::kDisabled_ReloadName, |
| true); |
| } |
| |
| // Another metadata update should not increase reload count. |
| metadata.behavior_flags |= |
| blink::WebLoadingBehaviorFlag::kWebLoadingBehaviorServiceWorkerControlled; |
| SimulateTimingAndMetadataUpdate(timing, metadata); |
| histogram_tester().ExpectTotalCount( |
| internal::kHistogramDocWriteBlockReloadCount, 2); |
| |
| histogram_tester().ExpectTotalCount(internal::kHistogramDocWriteBlockCount, |
| 0); |
| } |
| |
| TEST_F(DocumentWritePageLoadMetricsObserverTest, NoPossibleBlock) { |
| base::TimeDelta contentful_paint = base::TimeDelta::FromMilliseconds(1); |
| page_load_metrics::mojom::PageLoadTiming timing; |
| page_load_metrics::InitPageLoadTimingForTest(&timing); |
| timing.navigation_start = base::Time::FromDoubleT(1); |
| timing.paint_timing->first_contentful_paint = contentful_paint; |
| PopulateRequiredTimingFields(&timing); |
| |
| page_load_metrics::mojom::PageLoadMetadata metadata; |
| NavigateAndCommit(GURL("https://www.google.com/")); |
| SimulateTimingAndMetadataUpdate(timing, metadata); |
| |
| NavigateAndCommit(GURL("https://www.example.com/")); |
| AssertNoBlockHistogramsLogged(); |
| } |