1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
6 #include "chrome/browser/browser_process.h"
7 #include "components/page_load_metrics/browser/page_load_metrics_util.h"
8 #include "services/metrics/public/cpp/ukm_builders.h"
9 #include "services/metrics/public/cpp/ukm_recorder.h"
10 #include "third_party/blink/public/common/loader/loading_behavior_flag.h"
11
12 namespace internal {
13 const char kHistogramDocWriteBlockFirstContentfulPaint[] =
14 "PageLoad.Clients.DocWrite.Block.PaintTiming."
15 "NavigationToFirstContentfulPaint";
16 const char kHistogramDocWriteBlockParseStartToFirstContentfulPaint[] =
17 "PageLoad.Clients.DocWrite.Block.PaintTiming."
18 "ParseStartToFirstContentfulPaint";
19 const char kHistogramDocWriteBlockParseBlockedOnScriptLoad[] =
20 "PageLoad.Clients.DocWrite.Block.ParseTiming.ParseBlockedOnScriptLoad";
21 const char kHistogramDocWriteBlockParseBlockedOnScriptLoadDocumentWrite[] =
22 "PageLoad.Clients.DocWrite.Block.ParseTiming."
23 "ParseBlockedOnScriptLoadFromDocumentWrite";
24 const char kHistogramDocWriteBlockParseBlockedOnScriptExecution[] =
25 "PageLoad.Clients.DocWrite.Block.ParseTiming.ParseBlockedOnScriptExecution";
26 const char kHistogramDocWriteBlockParseBlockedOnScriptExecutionDocumentWrite[] =
27 "PageLoad.Clients.DocWrite.Block.ParseTiming."
28 "ParseBlockedOnScriptExecutionFromDocumentWrite";
29 const char kHistogramDocWriteBlockParseDuration[] =
30 "PageLoad.Clients.DocWrite.Block.ParseTiming.ParseDuration";
31
32 const char kBackgroundHistogramDocWriteBlockParseBlockedOnScriptLoad[] =
33 "PageLoad.Clients.DocWrite.Block.ParseTiming.ParseBlockedOnScriptLoad."
34 "Background";
35 const char kBackgroundDocWriteBlockParseBlockedOnScriptLoadDocumentWrite[] =
36 "PageLoad.Clients.DocWrite.Block.ParseTiming."
37 "ParseBlockedOnScriptLoadFromDocumentWrite.Background";
38 const char kBackgroundHistogramDocWriteBlockParseDuration[] =
39 "PageLoad.Clients.DocWrite.Block.ParseTiming.ParseDuration.Background";
40
41 const char kHistogramDocWriteBlockCount[] =
42 "PageLoad.Clients.DocWrite.Block.Count";
43 const char kHistogramDocWriteBlockReloadCount[] =
44 "PageLoad.Clients.DocWrite.Block.ReloadCount";
45 const char kHistogramDocWriteBlockLoadingBehavior[] =
46 "PageLoad.Clients.DocWrite.Block.DocumentWriteLoadingBehavior";
47
48 } // namespace internal
49
OnFirstContentfulPaintInPage(const page_load_metrics::mojom::PageLoadTiming & timing)50 void DocumentWritePageLoadMetricsObserver::OnFirstContentfulPaintInPage(
51 const page_load_metrics::mojom::PageLoadTiming& timing) {
52 if (GetDelegate().GetMainFrameMetadata().behavior_flags &
53 blink::LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlock) {
54 LogDocumentWriteBlockFirstContentfulPaint(timing);
55 }
56 }
57
58 void DocumentWritePageLoadMetricsObserver::
OnFirstMeaningfulPaintInMainFrameDocument(const page_load_metrics::mojom::PageLoadTiming & timing)59 OnFirstMeaningfulPaintInMainFrameDocument(
60 const page_load_metrics::mojom::PageLoadTiming& timing) {
61 if (GetDelegate().GetMainFrameMetadata().behavior_flags &
62 blink::LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlock) {
63 LogDocumentWriteBlockFirstMeaningfulPaint(timing);
64 }
65 }
66
OnParseStop(const page_load_metrics::mojom::PageLoadTiming & timing)67 void DocumentWritePageLoadMetricsObserver::OnParseStop(
68 const page_load_metrics::mojom::PageLoadTiming& timing) {
69 if (GetDelegate().GetMainFrameMetadata().behavior_flags &
70 blink::LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlock) {
71 LogDocumentWriteBlockParseStop(timing);
72 }
73 }
74
75 // static
LogLoadingBehaviorMetrics(DocumentWritePageLoadMetricsObserver::DocumentWriteLoadingBehavior behavior,ukm::SourceId source_id)76 void DocumentWritePageLoadMetricsObserver::LogLoadingBehaviorMetrics(
77 DocumentWritePageLoadMetricsObserver::DocumentWriteLoadingBehavior behavior,
78 ukm::SourceId source_id) {
79 UMA_HISTOGRAM_ENUMERATION(
80 internal::kHistogramDocWriteBlockLoadingBehavior, behavior,
81 DocumentWritePageLoadMetricsObserver::LOADING_BEHAVIOR_MAX);
82
83 // We only log the block and reload behaviors in UKM.
84 if (behavior != LOADING_BEHAVIOR_BLOCK &&
85 behavior != LOADING_BEHAVIOR_RELOAD) {
86 return;
87 }
88 ukm::builders::Intervention_DocumentWrite_ScriptBlock builder(source_id);
89 if (behavior == LOADING_BEHAVIOR_RELOAD)
90 builder.SetDisabled_Reload(true);
91 builder.Record(ukm::UkmRecorder::Get());
92 }
93
OnLoadingBehaviorObserved(content::RenderFrameHost * rfh,int behavior_flags)94 void DocumentWritePageLoadMetricsObserver::OnLoadingBehaviorObserved(
95 content::RenderFrameHost* rfh,
96 int behavior_flags) {
97 if ((GetDelegate().GetMainFrameMetadata().behavior_flags &
98 blink::LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlockReload) &&
99 !doc_write_block_reload_observed_) {
100 DCHECK(!(GetDelegate().GetMainFrameMetadata().behavior_flags &
101 blink::LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlock));
102 UMA_HISTOGRAM_COUNTS_1M(internal::kHistogramDocWriteBlockReloadCount, 1);
103 LogLoadingBehaviorMetrics(LOADING_BEHAVIOR_RELOAD,
104 GetDelegate().GetPageUkmSourceId());
105 doc_write_block_reload_observed_ = true;
106 }
107 if ((GetDelegate().GetMainFrameMetadata().behavior_flags &
108 blink::LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlock) &&
109 !doc_write_block_observed_) {
110 UMA_HISTOGRAM_BOOLEAN(internal::kHistogramDocWriteBlockCount, true);
111 LogLoadingBehaviorMetrics(LOADING_BEHAVIOR_BLOCK,
112 GetDelegate().GetPageUkmSourceId());
113 doc_write_block_observed_ = true;
114 }
115 if ((GetDelegate().GetMainFrameMetadata().behavior_flags &
116 blink::LoadingBehaviorFlag::
117 kLoadingBehaviorDocumentWriteBlockDifferentScheme) &&
118 !doc_write_same_site_diff_scheme_) {
119 LogLoadingBehaviorMetrics(LOADING_BEHAVIOR_SAME_SITE_DIFF_SCHEME,
120 GetDelegate().GetPageUkmSourceId());
121 doc_write_same_site_diff_scheme_ = true;
122 }
123 }
124
125 // Note: The first meaningful paint calculation in the core observer filters
126 // out pages which had user interaction before the first meaningful paint.
127 // Because the counts of those instances are low (< 2%), just log everything
128 // here for simplicity. If this ends up being unreliable (the 2% is just from
129 // canary), the page_load_metrics API should be altered to return the values
130 // the consumer wants.
131 void DocumentWritePageLoadMetricsObserver::
LogDocumentWriteBlockFirstMeaningfulPaint(const page_load_metrics::mojom::PageLoadTiming & timing)132 LogDocumentWriteBlockFirstMeaningfulPaint(
133 const page_load_metrics::mojom::PageLoadTiming& timing) {
134 if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground(
135 timing.paint_timing->first_meaningful_paint, GetDelegate())) {
136 PAGE_LOAD_HISTOGRAM(
137 "PageLoad.Clients.DocWrite.Block.Experimental.PaintTiming."
138 "ParseStartToFirstMeaningfulPaint",
139 timing.paint_timing->first_meaningful_paint.value() -
140 timing.parse_timing->parse_start.value());
141 }
142 }
143
144 void DocumentWritePageLoadMetricsObserver::
LogDocumentWriteBlockFirstContentfulPaint(const page_load_metrics::mojom::PageLoadTiming & timing)145 LogDocumentWriteBlockFirstContentfulPaint(
146 const page_load_metrics::mojom::PageLoadTiming& timing) {
147 if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground(
148 timing.paint_timing->first_contentful_paint, GetDelegate())) {
149 PAGE_LOAD_HISTOGRAM(internal::kHistogramDocWriteBlockFirstContentfulPaint,
150 timing.paint_timing->first_contentful_paint.value());
151 PAGE_LOAD_HISTOGRAM(
152 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint,
153 timing.paint_timing->first_contentful_paint.value() -
154 timing.parse_timing->parse_start.value());
155 }
156 }
157
LogDocumentWriteBlockParseStop(const page_load_metrics::mojom::PageLoadTiming & timing)158 void DocumentWritePageLoadMetricsObserver::LogDocumentWriteBlockParseStop(
159 const page_load_metrics::mojom::PageLoadTiming& timing) {
160 base::TimeDelta parse_duration = timing.parse_timing->parse_stop.value() -
161 timing.parse_timing->parse_start.value();
162 if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground(
163 timing.parse_timing->parse_stop, GetDelegate())) {
164 PAGE_LOAD_HISTOGRAM(internal::kHistogramDocWriteBlockParseDuration,
165 parse_duration);
166 PAGE_LOAD_HISTOGRAM(
167 internal::kHistogramDocWriteBlockParseBlockedOnScriptLoad,
168 timing.parse_timing->parse_blocked_on_script_load_duration.value());
169 PAGE_LOAD_HISTOGRAM(
170 internal::kHistogramDocWriteBlockParseBlockedOnScriptLoadDocumentWrite,
171 timing.parse_timing
172 ->parse_blocked_on_script_load_from_document_write_duration
173 .value());
174 PAGE_LOAD_HISTOGRAM(
175 internal::kHistogramDocWriteBlockParseBlockedOnScriptExecution,
176 timing.parse_timing->parse_blocked_on_script_execution_duration
177 .value());
178 PAGE_LOAD_HISTOGRAM(
179 internal::
180 kHistogramDocWriteBlockParseBlockedOnScriptExecutionDocumentWrite,
181 timing.parse_timing
182 ->parse_blocked_on_script_execution_from_document_write_duration
183 .value());
184
185 ukm::builders::Intervention_DocumentWrite_ScriptBlock(
186 GetDelegate().GetPageUkmSourceId())
187 .SetParseTiming_ParseBlockedOnScriptLoadFromDocumentWrite(
188 timing.parse_timing
189 ->parse_blocked_on_script_load_from_document_write_duration
190 ->InMilliseconds())
191 .SetParseTiming_ParseBlockedOnScriptExecutionFromDocumentWrite(
192 timing.parse_timing
193 ->parse_blocked_on_script_execution_from_document_write_duration
194 ->InMilliseconds())
195 .Record(ukm::UkmRecorder::Get());
196 } else {
197 PAGE_LOAD_HISTOGRAM(
198 internal::kBackgroundHistogramDocWriteBlockParseDuration,
199 parse_duration);
200 PAGE_LOAD_HISTOGRAM(
201 internal::kBackgroundHistogramDocWriteBlockParseBlockedOnScriptLoad,
202 timing.parse_timing->parse_blocked_on_script_load_duration.value());
203 PAGE_LOAD_HISTOGRAM(
204 internal::kBackgroundDocWriteBlockParseBlockedOnScriptLoadDocumentWrite,
205 timing.parse_timing
206 ->parse_blocked_on_script_load_from_document_write_duration
207 .value());
208 }
209 }
210