1 // Copyright 2015 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 <algorithm>
6 #include <iterator>
7 #include <memory>
8 #include <string>
9 #include <unordered_set>
10 #include <utility>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/check_op.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/macros.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/path_service.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_util.h"
22 #include "base/test/metrics/histogram_tester.h"
23 #include "base/test/scoped_feature_list.h"
24 #include "base/threading/thread_restrictions.h"
25 #include "base/time/time.h"
26 #include "build/build_config.h"
27 #include "chrome/browser/page_load_metrics/observers/aborts_page_load_metrics_observer.h"
28 #include "chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.h"
29 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
30 #include "chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h"
31 #include "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h"
32 #include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h"
33 #include "chrome/browser/prefetch/no_state_prefetch/prerender_manager_factory.h"
34 #include "chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h"
35 #include "chrome/browser/prefs/session_startup_pref.h"
36 #include "chrome/browser/profiles/profile.h"
37 #include "chrome/browser/sessions/session_restore.h"
38 #include "chrome/browser/sessions/session_restore_test_helper.h"
39 #include "chrome/browser/sessions/session_service_factory.h"
40 #include "chrome/browser/sessions/session_service_test_helper.h"
41 #include "chrome/browser/ui/browser.h"
42 #include "chrome/browser/ui/browser_commands.h"
43 #include "chrome/browser/ui/browser_list.h"
44 #include "chrome/browser/ui/browser_navigator_params.h"
45 #include "chrome/browser/ui/browser_window.h"
46 #include "chrome/browser/ui/tabs/tab_strip_model.h"
47 #include "chrome/common/chrome_features.h"
48 #include "chrome/common/chrome_paths.h"
49 #include "chrome/common/pref_names.h"
50 #include "chrome/common/url_constants.h"
51 #include "chrome/test/base/in_process_browser_test.h"
52 #include "chrome/test/base/ui_test_utils.h"
53 #include "components/keep_alive_registry/keep_alive_types.h"
54 #include "components/keep_alive_registry/scoped_keep_alive.h"
55 #include "components/no_state_prefetch/browser/prerender_handle.h"
56 #include "components/no_state_prefetch/browser/prerender_histograms.h"
57 #include "components/no_state_prefetch/browser/prerender_manager.h"
58 #include "components/no_state_prefetch/common/prerender_origin.h"
59 #include "components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h"
60 #include "components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h"
61 #include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h"
62 #include "components/page_load_metrics/browser/page_load_tracker.h"
63 #include "components/page_load_metrics/common/page_load_metrics_constants.h"
64 #include "components/prefs/pref_service.h"
65 #include "components/sessions/content/content_test_helper.h"
66 #include "components/sessions/core/serialized_navigation_entry.h"
67 #include "components/sessions/core/serialized_navigation_entry_test_helper.h"
68 #include "components/ukm/test_ukm_recorder.h"
69 #include "content/public/browser/browser_thread.h"
70 #include "content/public/browser/render_process_host.h"
71 #include "content/public/browser/render_view_host.h"
72 #include "content/public/common/content_features.h"
73 #include "content/public/common/referrer.h"
74 #include "content/public/test/browser_test.h"
75 #include "content/public/test/browser_test_utils.h"
76 #include "content/public/test/content_browser_test_utils.h"
77 #include "content/public/test/download_test_observer.h"
78 #include "content/public/test/navigation_handle_observer.h"
79 #include "content/public/test/test_navigation_observer.h"
80 #include "net/base/net_errors.h"
81 #include "net/dns/mock_host_resolver.h"
82 #include "net/test/embedded_test_server/controllable_http_response.h"
83 #include "net/test/embedded_test_server/embedded_test_server.h"
84 #include "services/metrics/public/cpp/ukm_builders.h"
85 #include "services/network/public/cpp/features.h"
86 #include "testing/gmock/include/gmock/gmock.h"
87 #include "testing/gtest/include/gtest/gtest.h"
88 #include "third_party/blink/public/common/features.h"
89 #include "third_party/blink/public/mojom/use_counter/css_property_id.mojom.h"
90 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
91 #include "ui/gfx/geometry/size.h"
92 #include "url/gurl.h"
93
94 using page_load_metrics::PageLoadMetricsTestWaiter;
95 using TimingField = page_load_metrics::PageLoadMetricsTestWaiter::TimingField;
96 using WebFeature = blink::mojom::WebFeature;
97 using testing::SizeIs;
98 using testing::UnorderedElementsAre;
99 using NoStatePrefetch = ukm::builders::NoStatePrefetch;
100
101 namespace {
102
103 constexpr char kCacheablePathPrefix[] = "/cacheable";
104
HandleCachableRequestHandler(const net::test_server::HttpRequest & request)105 std::unique_ptr<net::test_server::HttpResponse> HandleCachableRequestHandler(
106 const net::test_server::HttpRequest& request) {
107 if (!base::StartsWith(request.relative_url, kCacheablePathPrefix,
108 base::CompareCase::SENSITIVE)) {
109 return nullptr;
110 }
111
112 if (request.headers.find("If-None-Match") != request.headers.end()) {
113 return std::make_unique<net::test_server::RawHttpResponse>(
114 "HTTP/1.1 304 Not Modified", "");
115 }
116
117 auto response = std::make_unique<net::test_server::BasicHttpResponse>();
118 response->set_code(net::HTTP_OK);
119 response->set_content_type("text/html");
120 response->AddCustomHeader("cache-control", "max-age=60");
121 response->AddCustomHeader("etag", "foobar");
122 response->set_content("hi");
123 return std::move(response);
124 }
125
126 } // namespace
127
128 class PageLoadMetricsBrowserTest : public InProcessBrowserTest {
129 public:
PageLoadMetricsBrowserTest()130 PageLoadMetricsBrowserTest() {
131 scoped_feature_list_.InitWithFeatures(
132 {ukm::kUkmFeature, blink::features::kPortals,
133 blink::features::kPortalsCrossOrigin},
134 {});
135 }
136
~PageLoadMetricsBrowserTest()137 ~PageLoadMetricsBrowserTest() override {}
138
139 protected:
SetUpOnMainThread()140 void SetUpOnMainThread() override {
141 InProcessBrowserTest::SetUpOnMainThread();
142 host_resolver()->AddRule("*", "127.0.0.1");
143 embedded_test_server()->RegisterRequestHandler(
144 base::BindRepeating(&HandleCachableRequestHandler));
145 }
146
PreRunTestOnMainThread()147 void PreRunTestOnMainThread() override {
148 InProcessBrowserTest::PreRunTestOnMainThread();
149
150 histogram_tester_ = std::make_unique<base::HistogramTester>();
151 test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
152 }
153
154 // Force navigation to a new page, so the currently tracked page load runs its
155 // OnComplete callback. You should prefer to use PageLoadMetricsTestWaiter,
156 // and only use NavigateToUntrackedUrl for cases where the waiter isn't
157 // sufficient.
NavigateToUntrackedUrl()158 void NavigateToUntrackedUrl() {
159 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
160 }
161
MakeComponentFullscreen(const std::string & id)162 void MakeComponentFullscreen(const std::string& id) {
163 EXPECT_TRUE(content::ExecuteScript(
164 browser()->tab_strip_model()->GetActiveWebContents(),
165 "document.getElementById(\"" + id + "\").webkitRequestFullscreen();"));
166 }
167
GetRecordedPageLoadMetricNames()168 std::string GetRecordedPageLoadMetricNames() {
169 auto entries = histogram_tester_->GetTotalCountsForPrefix("PageLoad.");
170 std::vector<std::string> names;
171 std::transform(
172 entries.begin(), entries.end(), std::back_inserter(names),
173 [](const std::pair<std::string, base::HistogramBase::Count>& entry) {
174 return entry.first;
175 });
176 return base::JoinString(names, ",");
177 }
178
NoPageLoadMetricsRecorded()179 bool NoPageLoadMetricsRecorded() {
180 // Determine whether any 'public' page load metrics are recorded. We exclude
181 // 'internal' metrics as these may be recorded for debugging purposes.
182 size_t total_pageload_histograms =
183 histogram_tester_->GetTotalCountsForPrefix("PageLoad.").size();
184 size_t total_internal_histograms =
185 histogram_tester_->GetTotalCountsForPrefix("PageLoad.Internal.").size();
186 DCHECK_GE(total_pageload_histograms, total_internal_histograms);
187 return total_pageload_histograms - total_internal_histograms == 0;
188 }
189
CreatePageLoadMetricsTestWaiter()190 std::unique_ptr<PageLoadMetricsTestWaiter> CreatePageLoadMetricsTestWaiter() {
191 content::WebContents* web_contents =
192 browser()->tab_strip_model()->GetActiveWebContents();
193 return std::make_unique<PageLoadMetricsTestWaiter>(web_contents);
194 }
195
196 // Triggers nostate prefetch of |url|.
TriggerNoStatePrefetch(const GURL & url)197 void TriggerNoStatePrefetch(const GURL& url) {
198 prerender::PrerenderManager* prerender_manager =
199 prerender::PrerenderManagerFactory::GetForBrowserContext(
200 browser()->profile());
201 ASSERT_TRUE(prerender_manager);
202
203 prerender::test_utils::TestPrerenderContentsFactory*
204 prerender_contents_factory =
205 new prerender::test_utils::TestPrerenderContentsFactory();
206 prerender_manager->SetPrerenderContentsFactoryForTest(
207 prerender_contents_factory);
208
209 content::SessionStorageNamespace* storage_namespace =
210 browser()
211 ->tab_strip_model()
212 ->GetActiveWebContents()
213 ->GetController()
214 .GetDefaultSessionStorageNamespace();
215 ASSERT_TRUE(storage_namespace);
216
217 std::unique_ptr<prerender::test_utils::TestPrerender> test_prerender =
218 prerender_contents_factory->ExpectPrerenderContents(
219 prerender::FINAL_STATUS_NOSTATE_PREFETCH_FINISHED);
220
221 std::unique_ptr<prerender::PrerenderHandle> prerender_handle =
222 prerender_manager->AddPrerenderFromOmnibox(url, storage_namespace,
223 gfx::Size(640, 480));
224 ASSERT_EQ(prerender_handle->contents(), test_prerender->contents());
225
226 // The final status may be either FINAL_STATUS_NOSTATE_PREFETCH_FINISHED or
227 // FINAL_STATUS_RECENTLY_VISITED.
228 test_prerender->contents()->set_skip_final_checks(true);
229 }
230
VerifyBasicPageLoadUkms(const GURL & expected_source_url)231 void VerifyBasicPageLoadUkms(const GURL& expected_source_url) {
232 using PageLoad = ukm::builders::PageLoad;
233 const auto& entries =
234 test_ukm_recorder_->GetMergedEntriesByName(PageLoad::kEntryName);
235 EXPECT_EQ(1u, entries.size());
236 for (const auto& kv : entries) {
237 test_ukm_recorder_->ExpectEntrySourceHasUrl(kv.second.get(),
238 expected_source_url);
239 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
240 kv.second.get(),
241 PageLoad::
242 kDocumentTiming_NavigationToDOMContentLoadedEventFiredName));
243 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
244 kv.second.get(),
245 PageLoad::kDocumentTiming_NavigationToLoadEventFiredName));
246 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
247 kv.second.get(), PageLoad::kPaintTiming_NavigationToFirstPaintName));
248 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
249 kv.second.get(),
250 PageLoad::kPaintTiming_NavigationToFirstContentfulPaintName));
251 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
252 kv.second.get(), PageLoad::kMainFrameResource_SocketReusedName));
253 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
254 kv.second.get(), PageLoad::kMainFrameResource_DNSDelayName));
255 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
256 kv.second.get(), PageLoad::kMainFrameResource_ConnectDelayName));
257 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
258 kv.second.get(),
259 PageLoad::kMainFrameResource_RequestStartToSendStartName));
260 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
261 kv.second.get(),
262 PageLoad::kMainFrameResource_SendStartToReceiveHeadersEndName));
263 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
264 kv.second.get(),
265 PageLoad::kMainFrameResource_RequestStartToReceiveHeadersEndName));
266 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
267 kv.second.get(),
268 PageLoad::kMainFrameResource_NavigationStartToRequestStartName));
269 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
270 kv.second.get(),
271 PageLoad::kMainFrameResource_HttpProtocolSchemeName));
272 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
273 kv.second.get(), PageLoad::kSiteEngagementScoreName));
274 }
275 }
276
VerifyNavigationMetrics(std::vector<GURL> expected_source_urls)277 void VerifyNavigationMetrics(std::vector<GURL> expected_source_urls) {
278 int expected_count = expected_source_urls.size();
279
280 // Verify if the elapsed time from the navigation start are recorded.
281 histogram_tester_->ExpectTotalCount(
282 internal::kHistogramNavigationTimingNavigationStartToFirstRequestStart,
283 expected_count);
284 histogram_tester_->ExpectTotalCount(
285 internal::kHistogramNavigationTimingNavigationStartToFirstResponseStart,
286 expected_count);
287 histogram_tester_->ExpectTotalCount(
288 internal::
289 kHistogramNavigationTimingNavigationStartToFirstLoaderCallback,
290 expected_count);
291 histogram_tester_->ExpectTotalCount(
292 internal::kHistogramNavigationTimingNavigationStartToFinalRequestStart,
293 expected_count);
294 histogram_tester_->ExpectTotalCount(
295 internal::kHistogramNavigationTimingNavigationStartToFinalResponseStart,
296 expected_count);
297 histogram_tester_->ExpectTotalCount(
298 internal::
299 kHistogramNavigationTimingNavigationStartToFinalLoaderCallback,
300 expected_count);
301 histogram_tester_->ExpectTotalCount(
302 internal::
303 kHistogramNavigationTimingNavigationStartToNavigationCommitSent,
304 expected_count);
305
306 // Verify if the intervals between adjacent milestones are recorded.
307 histogram_tester_->ExpectTotalCount(
308 internal::
309 kHistogramNavigationTimingFirstRequestStartToFirstResponseStart,
310 expected_count);
311 histogram_tester_->ExpectTotalCount(
312 internal::
313 kHistogramNavigationTimingFirstResponseStartToFirstLoaderCallback,
314 expected_count);
315 histogram_tester_->ExpectTotalCount(
316 internal::
317 kHistogramNavigationTimingFinalRequestStartToFinalResponseStart,
318 expected_count);
319 histogram_tester_->ExpectTotalCount(
320 internal::
321 kHistogramNavigationTimingFinalResponseStartToFinalLoaderCallback,
322 expected_count);
323 histogram_tester_->ExpectTotalCount(
324 internal::
325 kHistogramNavigationTimingFinalLoaderCallbackToNavigationCommitSent,
326 expected_count);
327
328 using ukm::builders::NavigationTiming;
329 const std::vector<const char*> metrics = {
330 NavigationTiming::kFirstRequestStartName,
331 NavigationTiming::kFirstResponseStartName,
332 NavigationTiming::kFirstLoaderCallbackName,
333 NavigationTiming::kFinalRequestStartName,
334 NavigationTiming::kFinalResponseStartName,
335 NavigationTiming::kFinalLoaderCallbackName,
336 NavigationTiming::kNavigationCommitSentName};
337
338 const auto& entries = test_ukm_recorder_->GetMergedEntriesByName(
339 NavigationTiming::kEntryName);
340 ASSERT_EQ(expected_source_urls.size(), entries.size());
341 int i = 0;
342 for (const auto& kv : entries) {
343 test_ukm_recorder_->ExpectEntrySourceHasUrl(kv.second.get(),
344 expected_source_urls[i++]);
345
346 // Verify if the elapsed times from the navigation start are recorded.
347 for (const char* metric : metrics) {
348 EXPECT_TRUE(
349 test_ukm_recorder_->EntryHasMetric(kv.second.get(), metric));
350 }
351 }
352 }
353
354 enum class EarlyHintsPolicy {
355 // Navigation will receive no early hints response.
356 NoHints,
357
358 // Navigation will receive one early hints response.
359 OneHint,
360
361 // Navigation will receive multiple early hints responses.
362 MultipleHints,
363 };
364
NavigateWithEarlyHints(EarlyHintsPolicy policy)365 content::NavigationHandleTiming NavigateWithEarlyHints(
366 EarlyHintsPolicy policy) {
367 auto response =
368 std::make_unique<net::test_server::ControllableHttpResponse>(
369 embedded_test_server(), "/mock_page.html",
370 /*relative_url_is_prefix=*/true);
371
372 EXPECT_TRUE(embedded_test_server()->Start());
373
374 GURL url = embedded_test_server()->GetURL("/mock_page.html");
375
376 content::NavigationHandleObserver observer(
377 browser()->tab_strip_model()->GetActiveWebContents(), url);
378
379 browser()->OpenURL(content::OpenURLParams(
380 url, content::Referrer(), WindowOpenDisposition::CURRENT_TAB,
381 ui::PAGE_TRANSITION_TYPED, false));
382 response->WaitForRequest();
383
384 // Serve the Early Hints responses.
385 const char kHttpResponseHeader[] =
386 "HTTP/1.1 103 Early Hints\r\n"
387 "\r\n";
388 switch (policy) {
389 case EarlyHintsPolicy::NoHints:
390 break;
391 case EarlyHintsPolicy::OneHint:
392 response->Send(kHttpResponseHeader);
393 break;
394 case EarlyHintsPolicy::MultipleHints:
395 response->Send(kHttpResponseHeader);
396 response->Send(kHttpResponseHeader);
397 response->Send(kHttpResponseHeader);
398 break;
399 }
400
401 // Serve the main response.
402 const char kMainHttpResponseHeader[] =
403 "HTTP/1.1 200 OK\r\n"
404 "Content-Type: text/html; charset=utf-8\r\n"
405 "\r\n";
406 response->Send(kMainHttpResponseHeader);
407 response->Done();
408
409 // Wait until the navigation completes.
410 auto waiter = CreatePageLoadMetricsTestWaiter();
411 waiter->AddMinimumCompleteResourcesExpectation(1);
412 waiter->Wait();
413 EXPECT_TRUE(observer.has_committed());
414
415 // Force navigation to another page, which should force logging of
416 // histograms persisted at the end of the page load lifetime.
417 NavigateToUntrackedUrl();
418
419 VerifyNavigationMetrics({url});
420
421 return observer.navigation_handle_timing();
422 }
423
RedirectWithEarlyHints(EarlyHintsPolicy policy_for_first_request,EarlyHintsPolicy policy_for_final_request)424 content::NavigationHandleTiming RedirectWithEarlyHints(
425 EarlyHintsPolicy policy_for_first_request,
426 EarlyHintsPolicy policy_for_final_request) {
427 auto response1 =
428 std::make_unique<net::test_server::ControllableHttpResponse>(
429 embedded_test_server(), "/mock_page1.html",
430 /*relative_url_is_prefix=*/true);
431 auto response2 =
432 std::make_unique<net::test_server::ControllableHttpResponse>(
433 embedded_test_server(), "/mock_page2.html",
434 /*relative_url_is_prefix=*/true);
435
436 EXPECT_TRUE(embedded_test_server()->Start());
437
438 GURL url1 = embedded_test_server()->GetURL("/mock_page1.html");
439 GURL url2 = embedded_test_server()->GetURL("/mock_page2.html");
440
441 content::NavigationHandleObserver observer(
442 browser()->tab_strip_model()->GetActiveWebContents(), url1);
443
444 browser()->OpenURL(content::OpenURLParams(
445 url1, content::Referrer(), WindowOpenDisposition::CURRENT_TAB,
446 ui::PAGE_TRANSITION_TYPED, false));
447 response1->WaitForRequest();
448
449 // Serve the Early Hints responses for the first request.
450 const char kHttpResponseHeader[] =
451 "HTTP/1.1 103 Early Hints\r\n"
452 "\r\n";
453 switch (policy_for_first_request) {
454 case EarlyHintsPolicy::NoHints:
455 break;
456 case EarlyHintsPolicy::OneHint:
457 response1->Send(kHttpResponseHeader);
458 break;
459 case EarlyHintsPolicy::MultipleHints:
460 response1->Send(kHttpResponseHeader);
461 response1->Send(kHttpResponseHeader);
462 response1->Send(kHttpResponseHeader);
463 break;
464 }
465
466 // Serve the redirection response.
467 const char kHttpRedirectResponseHeader[] =
468 "HTTP/1.1 307 Temporary Redirect\r\n"
469 "Location: /mock_page2.html\r\n"
470 "\r\n";
471 response1->Send(kHttpRedirectResponseHeader);
472
473 // Wait for the redirected request.
474 response1->Done();
475 response2->WaitForRequest();
476
477 // Serve the Early Hints responses for the redirected request.
478 switch (policy_for_final_request) {
479 case EarlyHintsPolicy::NoHints:
480 break;
481 case EarlyHintsPolicy::OneHint:
482 response2->Send(kHttpResponseHeader);
483 break;
484 case EarlyHintsPolicy::MultipleHints:
485 response2->Send(kHttpResponseHeader);
486 response2->Send(kHttpResponseHeader);
487 response2->Send(kHttpResponseHeader);
488 break;
489 }
490
491 // Serve the main response.
492 const char kMainHttpResponseHeader[] =
493 "HTTP/1.1 200 OK\r\n"
494 "Content-Type: text/html; charset=utf-8\r\n"
495 "\r\n";
496 response2->Send(kMainHttpResponseHeader);
497 response2->Done();
498
499 // Wait until the navigation completes.
500 auto waiter = CreatePageLoadMetricsTestWaiter();
501 waiter->AddMinimumCompleteResourcesExpectation(1);
502 waiter->Wait();
503 EXPECT_TRUE(observer.has_committed());
504
505 // Force navigation to another page, which should force logging of
506 // histograms persisted at the end of the page load lifetime.
507 NavigateToUntrackedUrl();
508
509 VerifyNavigationMetrics({url2});
510
511 return observer.navigation_handle_timing();
512 }
513
web_contents() const514 content::WebContents* web_contents() const {
515 return browser()->tab_strip_model()->GetActiveWebContents();
516 }
517
RenderFrameHost() const518 content::RenderFrameHost* RenderFrameHost() const {
519 return web_contents()->GetMainFrame();
520 }
521 base::test::ScopedFeatureList scoped_feature_list_;
522 std::unique_ptr<base::HistogramTester> histogram_tester_;
523 std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
524
525 private:
526 DISALLOW_COPY_AND_ASSIGN(PageLoadMetricsBrowserTest);
527 };
528
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NoNavigation)529 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoNavigation) {
530 ASSERT_TRUE(embedded_test_server()->Start());
531 EXPECT_TRUE(NoPageLoadMetricsRecorded())
532 << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
533 }
534
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NewPage)535 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NewPage) {
536 ASSERT_TRUE(embedded_test_server()->Start());
537
538 GURL url = embedded_test_server()->GetURL("/title1.html");
539
540 auto waiter = CreatePageLoadMetricsTestWaiter();
541 waiter->AddPageExpectation(TimingField::kFirstPaint);
542 ui_test_utils::NavigateToURL(browser(), url);
543 waiter->Wait();
544
545 histogram_tester_->ExpectTotalCount(internal::kHistogramDomContentLoaded, 1);
546 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
547 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 1);
548 histogram_tester_->ExpectTotalCount(internal::kHistogramParseDuration, 1);
549 histogram_tester_->ExpectTotalCount(
550 internal::kHistogramParseBlockedOnScriptLoad, 1);
551 histogram_tester_->ExpectTotalCount(
552 internal::kHistogramParseBlockedOnScriptExecution, 1);
553
554 // Force navigation to another page, which should force logging of histograms
555 // persisted at the end of the page load lifetime.
556 NavigateToUntrackedUrl();
557 histogram_tester_->ExpectTotalCount(internal::kHistogramPageLoadTotalBytes,
558 1);
559 histogram_tester_->ExpectTotalCount(
560 internal::kHistogramPageTimingForegroundDuration, 1);
561
562 VerifyBasicPageLoadUkms(url);
563
564 const auto& nostate_prefetch_entries =
565 test_ukm_recorder_->GetMergedEntriesByName(NoStatePrefetch::kEntryName);
566 EXPECT_EQ(0u, nostate_prefetch_entries.size());
567
568 VerifyNavigationMetrics({url});
569 }
570
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,Redirect)571 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, Redirect) {
572 ASSERT_TRUE(embedded_test_server()->Start());
573
574 GURL final_url = embedded_test_server()->GetURL("/title1.html");
575 GURL first_url =
576 embedded_test_server()->GetURL("/server-redirect?" + final_url.spec());
577
578 auto waiter = CreatePageLoadMetricsTestWaiter();
579 waiter->AddPageExpectation(TimingField::kFirstPaint);
580 ui_test_utils::NavigateToURL(browser(), first_url);
581 waiter->Wait();
582
583 histogram_tester_->ExpectTotalCount(internal::kHistogramDomContentLoaded, 1);
584 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
585 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 1);
586 histogram_tester_->ExpectTotalCount(internal::kHistogramParseDuration, 1);
587 histogram_tester_->ExpectTotalCount(
588 internal::kHistogramParseBlockedOnScriptLoad, 1);
589 histogram_tester_->ExpectTotalCount(
590 internal::kHistogramParseBlockedOnScriptExecution, 1);
591
592 // Force navigation to another page, which should force logging of histograms
593 // persisted at the end of the page load lifetime.
594 NavigateToUntrackedUrl();
595 histogram_tester_->ExpectTotalCount(internal::kHistogramPageLoadTotalBytes,
596 1);
597 histogram_tester_->ExpectTotalCount(
598 internal::kHistogramPageTimingForegroundDuration, 1);
599
600 VerifyBasicPageLoadUkms(final_url);
601
602 const auto& nostate_prefetch_entries =
603 test_ukm_recorder_->GetMergedEntriesByName(NoStatePrefetch::kEntryName);
604 EXPECT_EQ(0u, nostate_prefetch_entries.size());
605
606 VerifyNavigationMetrics({final_url});
607 }
608
609 // Triggers nostate prefetch, and verifies that the UKM metrics related to
610 // nostate prefetch are recorded correctly.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NoStatePrefetchMetrics)611 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoStatePrefetchMetrics) {
612 ASSERT_TRUE(embedded_test_server()->Start());
613
614 GURL url = embedded_test_server()->GetURL("/title1.html");
615
616 TriggerNoStatePrefetch(url);
617
618 auto waiter = CreatePageLoadMetricsTestWaiter();
619 waiter->AddPageExpectation(TimingField::kFirstPaint);
620 ui_test_utils::NavigateToURL(browser(), url);
621 waiter->Wait();
622
623 // Force navigation to another page, which should force logging of histograms
624 // persisted at the end of the page load lifetime.
625 NavigateToUntrackedUrl();
626 histogram_tester_->ExpectTotalCount(internal::kHistogramPageLoadTotalBytes,
627 1);
628 histogram_tester_->ExpectTotalCount(
629 internal::kHistogramPageTimingForegroundDuration, 1);
630
631 const auto& entries =
632 test_ukm_recorder_->GetMergedEntriesByName(NoStatePrefetch::kEntryName);
633 EXPECT_EQ(1u, entries.size());
634 for (const auto& kv : entries) {
635 test_ukm_recorder_->ExpectEntrySourceHasUrl(kv.second.get(), url);
636 // UKM metrics related to attempted nostate prefetch should be recorded.
637 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
638 kv.second.get(), NoStatePrefetch::kPrefetchedRecently_FinalStatusName));
639 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
640 kv.second.get(), NoStatePrefetch::kPrefetchedRecently_OriginName));
641 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
642 kv.second.get(), NoStatePrefetch::kPrefetchedRecently_PrefetchAgeName));
643 }
644
645 VerifyNavigationMetrics({url});
646 }
647
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,CachedPage)648 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, CachedPage) {
649 ASSERT_TRUE(embedded_test_server()->Start());
650
651 GURL url = embedded_test_server()->GetURL(kCacheablePathPrefix);
652
653 // Navigate to the |url| to cache the main resource.
654 ui_test_utils::NavigateToURL(browser(), url);
655 NavigateToUntrackedUrl();
656
657 using PageLoad = ukm::builders::PageLoad;
658 auto entries =
659 test_ukm_recorder_->GetMergedEntriesByName(PageLoad::kEntryName);
660 EXPECT_EQ(1u, entries.size());
661 for (const auto& kv : entries) {
662 auto* const uncached_load_entry = kv.second.get();
663 test_ukm_recorder_->ExpectEntrySourceHasUrl(uncached_load_entry, url);
664
665 EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(uncached_load_entry,
666 PageLoad::kWasCachedName));
667 }
668
669 VerifyNavigationMetrics({url});
670
671 // Reset the recorders so it would only contain the cached pageload.
672 histogram_tester_ = std::make_unique<base::HistogramTester>();
673 test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
674
675 // Second navigation to the |url| should hit cache.
676 ui_test_utils::NavigateToURL(browser(), url);
677
678 // Force navigation to another page, which should force logging of histograms
679 // persisted at the end of the page load lifetime.
680 NavigateToUntrackedUrl();
681
682 entries = test_ukm_recorder_->GetMergedEntriesByName(PageLoad::kEntryName);
683 EXPECT_EQ(1u, entries.size());
684 for (const auto& kv : entries) {
685 auto* const cached_load_entry = kv.second.get();
686 test_ukm_recorder_->ExpectEntrySourceHasUrl(cached_load_entry, url);
687
688 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(cached_load_entry,
689 PageLoad::kWasCachedName));
690 }
691
692 VerifyNavigationMetrics({url});
693 }
694
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NewPageInNewForegroundTab)695 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NewPageInNewForegroundTab) {
696 ASSERT_TRUE(embedded_test_server()->Start());
697
698 NavigateParams params(browser(),
699 embedded_test_server()->GetURL("/title1.html"),
700 ui::PAGE_TRANSITION_LINK);
701 params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
702
703 Navigate(¶ms);
704 auto waiter = std::make_unique<PageLoadMetricsTestWaiter>(
705 params.navigated_or_inserted_contents);
706 waiter->AddPageExpectation(TimingField::kLoadEvent);
707 waiter->Wait();
708
709 // Due to crbug.com/725347, with browser side navigation enabled, navigations
710 // in new tabs were recorded as starting in the background. Here we verify
711 // that navigations initiated in a new tab are recorded as happening in the
712 // foreground.
713 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
714 histogram_tester_->ExpectTotalCount(internal::kBackgroundHistogramLoad, 0);
715 }
716
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NoPaintForEmptyDocument)717 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoPaintForEmptyDocument) {
718 ASSERT_TRUE(embedded_test_server()->Start());
719
720 auto waiter = CreatePageLoadMetricsTestWaiter();
721 waiter->AddPageExpectation(TimingField::kLoadEvent);
722 ui_test_utils::NavigateToURL(browser(),
723 embedded_test_server()->GetURL("/empty.html"));
724 waiter->Wait();
725 EXPECT_FALSE(waiter->DidObserveInPage(TimingField::kFirstPaint));
726
727 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
728 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 0);
729 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
730 0);
731 }
732
733 // TODO(crbug.com/986642): Flaky on Win and Linux.
734 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
735 #define MAYBE_NoPaintForEmptyDocumentInChildFrame \
736 DISABLED_NoPaintForEmptyDocumentInChildFrame
737 #else
738 #define MAYBE_NoPaintForEmptyDocumentInChildFrame \
739 NoPaintForEmptyDocumentInChildFrame
740 #endif
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MAYBE_NoPaintForEmptyDocumentInChildFrame)741 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
742 MAYBE_NoPaintForEmptyDocumentInChildFrame) {
743 ASSERT_TRUE(embedded_test_server()->Start());
744
745 GURL a_url(
746 embedded_test_server()->GetURL("/page_load_metrics/empty_iframe.html"));
747
748 auto waiter = CreatePageLoadMetricsTestWaiter();
749 waiter->AddPageExpectation(TimingField::kLoadEvent);
750 waiter->AddSubFrameExpectation(TimingField::kLoadEvent);
751 ui_test_utils::NavigateToURL(browser(), a_url);
752 waiter->Wait();
753 EXPECT_FALSE(waiter->DidObserveInPage(TimingField::kFirstPaint));
754
755 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
756 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 0);
757 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
758 0);
759 }
760
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PaintInChildFrame)761 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PaintInChildFrame) {
762 ASSERT_TRUE(embedded_test_server()->Start());
763
764 GURL a_url(embedded_test_server()->GetURL("/page_load_metrics/iframe.html"));
765 auto waiter = CreatePageLoadMetricsTestWaiter();
766 waiter->AddPageExpectation(TimingField::kLoadEvent);
767 waiter->AddPageExpectation(TimingField::kFirstPaint);
768 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
769 waiter->AddSubFrameExpectation(TimingField::kFirstPaint);
770 waiter->AddSubFrameExpectation(TimingField::kFirstContentfulPaint);
771 ui_test_utils::NavigateToURL(browser(), a_url);
772 waiter->Wait();
773
774 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
775 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 1);
776 }
777
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PaintInDynamicChildFrame)778 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PaintInDynamicChildFrame) {
779 ASSERT_TRUE(embedded_test_server()->Start());
780
781 auto waiter = CreatePageLoadMetricsTestWaiter();
782 waiter->AddPageExpectation(TimingField::kLoadEvent);
783 waiter->AddPageExpectation(TimingField::kFirstPaint);
784 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
785 waiter->AddSubFrameExpectation(TimingField::kFirstPaint);
786 waiter->AddSubFrameExpectation(TimingField::kFirstContentfulPaint);
787 ui_test_utils::NavigateToURL(
788 browser(),
789 embedded_test_server()->GetURL("/page_load_metrics/dynamic_iframe.html"));
790 waiter->Wait();
791
792 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
793 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 1);
794 }
795
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PaintInMultipleChildFrames)796 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PaintInMultipleChildFrames) {
797 ASSERT_TRUE(embedded_test_server()->Start());
798
799 GURL a_url(embedded_test_server()->GetURL("/page_load_metrics/iframes.html"));
800
801 auto waiter = CreatePageLoadMetricsTestWaiter();
802 waiter->AddPageExpectation(TimingField::kLoadEvent);
803
804 waiter->AddSubFrameExpectation(TimingField::kFirstPaint);
805 waiter->AddPageExpectation(TimingField::kFirstPaint);
806
807 waiter->AddSubFrameExpectation(TimingField::kFirstContentfulPaint);
808 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
809
810 ui_test_utils::NavigateToURL(browser(), a_url);
811 waiter->Wait();
812
813 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
814 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 1);
815 }
816
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PaintInMainAndChildFrame)817 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PaintInMainAndChildFrame) {
818 ASSERT_TRUE(embedded_test_server()->Start());
819
820 GURL a_url(embedded_test_server()->GetURL(
821 "/page_load_metrics/main_frame_with_iframe.html"));
822
823 auto waiter = CreatePageLoadMetricsTestWaiter();
824 waiter->AddPageExpectation(TimingField::kLoadEvent);
825 waiter->AddPageExpectation(TimingField::kFirstPaint);
826 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
827 waiter->AddSubFrameExpectation(TimingField::kFirstPaint);
828 waiter->AddSubFrameExpectation(TimingField::kFirstContentfulPaint);
829 ui_test_utils::NavigateToURL(browser(), a_url);
830 waiter->Wait();
831
832 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
833 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 1);
834 }
835
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,SameDocumentNavigation)836 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, SameDocumentNavigation) {
837 ASSERT_TRUE(embedded_test_server()->Start());
838
839 auto waiter = CreatePageLoadMetricsTestWaiter();
840 waiter->AddPageExpectation(TimingField::kLoadEvent);
841 GURL url = embedded_test_server()->GetURL("/title1.html");
842 ui_test_utils::NavigateToURL(browser(), url);
843 waiter->Wait();
844
845 histogram_tester_->ExpectTotalCount(internal::kHistogramDomContentLoaded, 1);
846 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
847
848 // Perform a same-document navigation. No additional metrics should be logged.
849 ui_test_utils::NavigateToURL(
850 browser(), embedded_test_server()->GetURL("/title1.html#hash"));
851 NavigateToUntrackedUrl();
852
853 histogram_tester_->ExpectTotalCount(internal::kHistogramDomContentLoaded, 1);
854 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
855
856 VerifyNavigationMetrics({url});
857 }
858
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,SameUrlNavigation)859 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, SameUrlNavigation) {
860 ASSERT_TRUE(embedded_test_server()->Start());
861
862 auto waiter = CreatePageLoadMetricsTestWaiter();
863 waiter->AddPageExpectation(TimingField::kLoadEvent);
864 GURL url = embedded_test_server()->GetURL("/title1.html");
865 ui_test_utils::NavigateToURL(browser(), url);
866 waiter->Wait();
867
868 histogram_tester_->ExpectTotalCount(internal::kHistogramDomContentLoaded, 1);
869 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 1);
870
871 waiter = CreatePageLoadMetricsTestWaiter();
872 waiter->AddPageExpectation(TimingField::kLoadEvent);
873 ui_test_utils::NavigateToURL(browser(), url);
874 waiter->Wait();
875
876 VerifyNavigationMetrics({url});
877
878 // We expect one histogram sample for each navigation to title1.html.
879 histogram_tester_->ExpectTotalCount(internal::kHistogramDomContentLoaded, 2);
880 histogram_tester_->ExpectTotalCount(internal::kHistogramLoad, 2);
881
882 // Force navigation to another page, which should force logging of histograms
883 // persisted at the end of the page load lifetime.
884 NavigateToUntrackedUrl();
885
886 VerifyNavigationMetrics({url, url});
887 }
888
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DocWriteAbortsSubframeNavigation)889 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
890 DocWriteAbortsSubframeNavigation) {
891 ASSERT_TRUE(embedded_test_server()->Start());
892
893 auto waiter = CreatePageLoadMetricsTestWaiter();
894 ui_test_utils::NavigateToURL(
895 browser(), embedded_test_server()->GetURL(
896 "/page_load_metrics/doc_write_aborts_subframe.html"));
897 waiter->AddMinimumCompleteResourcesExpectation(4);
898 waiter->Wait();
899 EXPECT_FALSE(waiter->DidObserveInPage(TimingField::kFirstPaint));
900 }
901
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NonHtmlMainResource)902 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NonHtmlMainResource) {
903 ASSERT_TRUE(embedded_test_server()->Start());
904
905 ui_test_utils::NavigateToURL(browser(),
906 embedded_test_server()->GetURL("/circle.svg"));
907 NavigateToUntrackedUrl();
908 EXPECT_TRUE(NoPageLoadMetricsRecorded())
909 << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
910 }
911
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NonHttpOrHttpsUrl)912 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NonHttpOrHttpsUrl) {
913 ASSERT_TRUE(embedded_test_server()->Start());
914
915 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
916 NavigateToUntrackedUrl();
917 EXPECT_TRUE(NoPageLoadMetricsRecorded())
918 << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
919 }
920
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,HttpErrorPage)921 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, HttpErrorPage) {
922 ASSERT_TRUE(embedded_test_server()->Start());
923
924 ui_test_utils::NavigateToURL(
925 browser(), embedded_test_server()->GetURL("/page_load_metrics/404.html"));
926 NavigateToUntrackedUrl();
927 EXPECT_TRUE(NoPageLoadMetricsRecorded())
928 << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
929 }
930
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,ChromeErrorPage)931 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ChromeErrorPage) {
932 ASSERT_TRUE(embedded_test_server()->Start());
933 GURL url = embedded_test_server()->GetURL("/title1.html");
934 // By shutting down the server, we ensure a failure.
935 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
936 content::NavigationHandleObserver observer(
937 browser()->tab_strip_model()->GetActiveWebContents(), url);
938 ui_test_utils::NavigateToURL(browser(), url);
939 ASSERT_TRUE(observer.is_error());
940 NavigateToUntrackedUrl();
941 EXPECT_TRUE(NoPageLoadMetricsRecorded())
942 << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
943 }
944
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,Ignore204Pages)945 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, Ignore204Pages) {
946 ASSERT_TRUE(embedded_test_server()->Start());
947
948 ui_test_utils::NavigateToURL(browser(),
949 embedded_test_server()->GetURL("/page204.html"));
950 NavigateToUntrackedUrl();
951 EXPECT_TRUE(NoPageLoadMetricsRecorded())
952 << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
953 }
954
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,IgnoreDownloads)955 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, IgnoreDownloads) {
956 ASSERT_TRUE(embedded_test_server()->Start());
957
958 content::DownloadTestObserverTerminal downloads_observer(
959 content::BrowserContext::GetDownloadManager(browser()->profile()),
960 1, // == wait_count (only waiting for "download-test3.gif").
961 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
962
963 ui_test_utils::NavigateToURL(
964 browser(), embedded_test_server()->GetURL("/download-test3.gif"));
965 downloads_observer.WaitForFinished();
966
967 NavigateToUntrackedUrl();
968 EXPECT_TRUE(NoPageLoadMetricsRecorded())
969 << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
970 }
971
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NoDocumentWrite)972 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoDocumentWrite) {
973 ASSERT_TRUE(embedded_test_server()->Start());
974
975 auto waiter = CreatePageLoadMetricsTestWaiter();
976 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
977
978 ui_test_utils::NavigateToURL(browser(),
979 embedded_test_server()->GetURL("/title1.html"));
980 waiter->Wait();
981
982 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
983 1);
984 histogram_tester_->ExpectTotalCount(
985 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
986 histogram_tester_->ExpectTotalCount(internal::kHistogramDocWriteBlockCount,
987 0);
988 }
989
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DocumentWriteBlock)990 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, DocumentWriteBlock) {
991 ASSERT_TRUE(embedded_test_server()->Start());
992
993 auto waiter = CreatePageLoadMetricsTestWaiter();
994 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
995
996 ui_test_utils::NavigateToURL(
997 browser(), embedded_test_server()->GetURL(
998 "/page_load_metrics/document_write_script_block.html"));
999 waiter->Wait();
1000
1001 histogram_tester_->ExpectTotalCount(
1002 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1);
1003 histogram_tester_->ExpectTotalCount(internal::kHistogramDocWriteBlockCount,
1004 1);
1005 }
1006
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DocumentWriteReload)1007 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, DocumentWriteReload) {
1008 ASSERT_TRUE(embedded_test_server()->Start());
1009
1010 auto waiter = CreatePageLoadMetricsTestWaiter();
1011 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
1012 ui_test_utils::NavigateToURL(
1013 browser(), embedded_test_server()->GetURL(
1014 "/page_load_metrics/document_write_script_block.html"));
1015 waiter->Wait();
1016
1017 histogram_tester_->ExpectTotalCount(
1018 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1);
1019 histogram_tester_->ExpectTotalCount(internal::kHistogramDocWriteBlockCount,
1020 1);
1021
1022 // Reload should not log the histogram as the script is not blocked.
1023 waiter = CreatePageLoadMetricsTestWaiter();
1024 waiter->AddPageExpectation(TimingField::kDocumentWriteBlockReload);
1025 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
1026 ui_test_utils::NavigateToURL(
1027 browser(), embedded_test_server()->GetURL(
1028 "/page_load_metrics/document_write_script_block.html"));
1029 waiter->Wait();
1030
1031 histogram_tester_->ExpectTotalCount(
1032 internal::kHistogramDocWriteBlockReloadCount, 1);
1033
1034 waiter = CreatePageLoadMetricsTestWaiter();
1035 waiter->AddPageExpectation(TimingField::kDocumentWriteBlockReload);
1036 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
1037 ui_test_utils::NavigateToURL(
1038 browser(), embedded_test_server()->GetURL(
1039 "/page_load_metrics/document_write_script_block.html"));
1040 waiter->Wait();
1041
1042 histogram_tester_->ExpectTotalCount(
1043 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1);
1044
1045 histogram_tester_->ExpectTotalCount(
1046 internal::kHistogramDocWriteBlockReloadCount, 2);
1047 histogram_tester_->ExpectTotalCount(internal::kHistogramDocWriteBlockCount,
1048 1);
1049 }
1050
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DocumentWriteAsync)1051 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, DocumentWriteAsync) {
1052 ASSERT_TRUE(embedded_test_server()->Start());
1053
1054 auto waiter = CreatePageLoadMetricsTestWaiter();
1055 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
1056 ui_test_utils::NavigateToURL(
1057 browser(), embedded_test_server()->GetURL(
1058 "/page_load_metrics/document_write_async_script.html"));
1059 waiter->Wait();
1060
1061 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
1062 1);
1063 histogram_tester_->ExpectTotalCount(
1064 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
1065 histogram_tester_->ExpectTotalCount(internal::kHistogramDocWriteBlockCount,
1066 0);
1067 }
1068
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DocumentWriteSameDomain)1069 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, DocumentWriteSameDomain) {
1070 ASSERT_TRUE(embedded_test_server()->Start());
1071
1072 auto waiter = CreatePageLoadMetricsTestWaiter();
1073 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
1074 ui_test_utils::NavigateToURL(
1075 browser(), embedded_test_server()->GetURL(
1076 "/page_load_metrics/document_write_external_script.html"));
1077 waiter->Wait();
1078
1079 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
1080 1);
1081 histogram_tester_->ExpectTotalCount(
1082 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
1083 histogram_tester_->ExpectTotalCount(internal::kHistogramDocWriteBlockCount,
1084 0);
1085 }
1086
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NoDocumentWriteScript)1087 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoDocumentWriteScript) {
1088 ASSERT_TRUE(embedded_test_server()->Start());
1089
1090 auto waiter = CreatePageLoadMetricsTestWaiter();
1091 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
1092 ui_test_utils::NavigateToURL(
1093 browser(), embedded_test_server()->GetURL(
1094 "/page_load_metrics/document_write_no_script.html"));
1095 waiter->Wait();
1096
1097 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
1098 1);
1099 histogram_tester_->ExpectTotalCount(
1100 internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
1101 histogram_tester_->ExpectTotalCount(internal::kHistogramDocWriteBlockCount,
1102 0);
1103 }
1104
1105 // TODO(crbug.com/712935): Flaky on Linux dbg.
1106 // TODO(crbug.com/738235): Now flaky on Win and Mac.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DISABLED_BadXhtml)1107 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, DISABLED_BadXhtml) {
1108 ASSERT_TRUE(embedded_test_server()->Start());
1109
1110 // When an XHTML page contains invalid XML, it causes a paint of the error
1111 // message without a layout. Page load metrics currently treats this as an
1112 // error. Eventually, we'll fix this by special casing the handling of
1113 // documents with non-well-formed XML on the blink side. See crbug.com/627607
1114 // for more.
1115 ui_test_utils::NavigateToURL(
1116 browser(),
1117 embedded_test_server()->GetURL("/page_load_metrics/badxml.xhtml"));
1118 NavigateToUntrackedUrl();
1119
1120 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 0);
1121
1122 histogram_tester_->ExpectBucketCount(
1123 page_load_metrics::internal::kErrorEvents,
1124 page_load_metrics::ERR_BAD_TIMING_IPC_INVALID_TIMING, 1);
1125
1126 histogram_tester_->ExpectTotalCount(
1127 page_load_metrics::internal::kPageLoadTimingStatus, 1);
1128 histogram_tester_->ExpectBucketCount(
1129 page_load_metrics::internal::kPageLoadTimingStatus,
1130 page_load_metrics::internal::INVALID_ORDER_PARSE_START_FIRST_PAINT, 1);
1131 }
1132
1133 // Test code that aborts provisional navigations.
1134 // TODO(csharrison): Move these to unit tests once the navigation API in content
1135 // properly calls NavigationHandle/NavigationThrottle methods.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,AbortNewNavigation)1136 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, AbortNewNavigation) {
1137 ASSERT_TRUE(embedded_test_server()->Start());
1138
1139 GURL url(embedded_test_server()->GetURL("/title1.html"));
1140 NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK);
1141 content::TestNavigationManager manager(
1142 browser()->tab_strip_model()->GetActiveWebContents(), url);
1143
1144 Navigate(¶ms);
1145 EXPECT_TRUE(manager.WaitForRequestStart());
1146
1147 GURL url2(embedded_test_server()->GetURL("/title2.html"));
1148 NavigateParams params2(browser(), url2, ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
1149
1150 auto waiter = CreatePageLoadMetricsTestWaiter();
1151 waiter->AddPageExpectation(TimingField::kLoadEvent);
1152 Navigate(¶ms2);
1153 waiter->Wait();
1154
1155 histogram_tester_->ExpectTotalCount(
1156 internal::kHistogramAbortNewNavigationBeforeCommit, 1);
1157 }
1158
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,AbortReload)1159 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, AbortReload) {
1160 ASSERT_TRUE(embedded_test_server()->Start());
1161
1162 GURL url(embedded_test_server()->GetURL("/title1.html"));
1163 NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK);
1164 content::TestNavigationManager manager(
1165 browser()->tab_strip_model()->GetActiveWebContents(), url);
1166
1167 Navigate(¶ms);
1168 EXPECT_TRUE(manager.WaitForRequestStart());
1169
1170 NavigateParams params2(browser(), url, ui::PAGE_TRANSITION_RELOAD);
1171
1172 auto waiter = CreatePageLoadMetricsTestWaiter();
1173 waiter->AddPageExpectation(TimingField::kLoadEvent);
1174 Navigate(¶ms2);
1175 waiter->Wait();
1176
1177 histogram_tester_->ExpectTotalCount(
1178 internal::kHistogramAbortReloadBeforeCommit, 1);
1179 }
1180
1181 // TODO(crbug.com/675061): Flaky on Win7 dbg.
1182 #if defined(OS_WIN)
1183 #define MAYBE_AbortClose DISABLED_AbortClose
1184 #else
1185 #define MAYBE_AbortClose AbortClose
1186 #endif
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MAYBE_AbortClose)1187 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, MAYBE_AbortClose) {
1188 ASSERT_TRUE(embedded_test_server()->Start());
1189
1190 GURL url(embedded_test_server()->GetURL("/title1.html"));
1191 NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK);
1192 content::TestNavigationManager manager(
1193 browser()->tab_strip_model()->GetActiveWebContents(), url);
1194
1195 Navigate(¶ms);
1196 EXPECT_TRUE(manager.WaitForRequestStart());
1197
1198 browser()->tab_strip_model()->GetActiveWebContents()->Close();
1199
1200 manager.WaitForNavigationFinished();
1201
1202 histogram_tester_->ExpectTotalCount(
1203 internal::kHistogramAbortCloseBeforeCommit, 1);
1204 }
1205
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,AbortMultiple)1206 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, AbortMultiple) {
1207 ASSERT_TRUE(embedded_test_server()->Start());
1208
1209 GURL url(embedded_test_server()->GetURL("/title1.html"));
1210 NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK);
1211 content::TestNavigationManager manager(
1212 browser()->tab_strip_model()->GetActiveWebContents(), url);
1213
1214 Navigate(¶ms);
1215 EXPECT_TRUE(manager.WaitForRequestStart());
1216
1217 GURL url2(embedded_test_server()->GetURL("/title2.html"));
1218 NavigateParams params2(browser(), url2, ui::PAGE_TRANSITION_TYPED);
1219 content::TestNavigationManager manager2(
1220 browser()->tab_strip_model()->GetActiveWebContents(), url2);
1221 Navigate(¶ms2);
1222
1223 EXPECT_TRUE(manager2.WaitForRequestStart());
1224 manager.WaitForNavigationFinished();
1225
1226 GURL url3(embedded_test_server()->GetURL("/title3.html"));
1227 NavigateParams params3(browser(), url3, ui::PAGE_TRANSITION_TYPED);
1228
1229 auto waiter = CreatePageLoadMetricsTestWaiter();
1230 waiter->AddPageExpectation(TimingField::kLoadEvent);
1231 Navigate(¶ms3);
1232 waiter->Wait();
1233
1234 manager2.WaitForNavigationFinished();
1235
1236 histogram_tester_->ExpectTotalCount(
1237 internal::kHistogramAbortNewNavigationBeforeCommit, 2);
1238 }
1239
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,NoAbortMetricsOnClientRedirect)1240 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1241 NoAbortMetricsOnClientRedirect) {
1242 ASSERT_TRUE(embedded_test_server()->Start());
1243
1244 GURL first_url(embedded_test_server()->GetURL("/title1.html"));
1245 ui_test_utils::NavigateToURL(browser(), first_url);
1246
1247 GURL second_url(embedded_test_server()->GetURL("/title2.html"));
1248 NavigateParams params(browser(), second_url, ui::PAGE_TRANSITION_LINK);
1249 content::TestNavigationManager manager(
1250 browser()->tab_strip_model()->GetActiveWebContents(), second_url);
1251 Navigate(¶ms);
1252 EXPECT_TRUE(manager.WaitForRequestStart());
1253
1254 {
1255 auto waiter = CreatePageLoadMetricsTestWaiter();
1256 waiter->AddPageExpectation(TimingField::kLoadEvent);
1257 EXPECT_TRUE(content::ExecuteScript(
1258 browser()->tab_strip_model()->GetActiveWebContents(),
1259 "window.location.reload();"));
1260 waiter->Wait();
1261 }
1262
1263 manager.WaitForNavigationFinished();
1264
1265 EXPECT_TRUE(
1266 histogram_tester_
1267 ->GetTotalCountsForPrefix("PageLoad.Experimental.AbortTiming.")
1268 .empty());
1269 }
1270
1271 // TODO(crbug.com/1009885): Flaky on Linux MSan builds.
1272 #if defined(MEMORY_SANITIZER) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
1273 #define MAYBE_FirstMeaningfulPaintRecorded DISABLED_FirstMeaningfulPaintRecorded
1274 #else
1275 #define MAYBE_FirstMeaningfulPaintRecorded FirstMeaningfulPaintRecorded
1276 #endif
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MAYBE_FirstMeaningfulPaintRecorded)1277 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1278 MAYBE_FirstMeaningfulPaintRecorded) {
1279 ASSERT_TRUE(embedded_test_server()->Start());
1280
1281 auto waiter = CreatePageLoadMetricsTestWaiter();
1282 waiter->AddPageExpectation(TimingField::kFirstMeaningfulPaint);
1283 ui_test_utils::NavigateToURL(browser(),
1284 embedded_test_server()->GetURL("/title1.html"));
1285 waiter->Wait();
1286
1287 histogram_tester_->ExpectUniqueSample(
1288 internal::kHistogramFirstMeaningfulPaintStatus,
1289 internal::FIRST_MEANINGFUL_PAINT_RECORDED, 1);
1290 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstMeaningfulPaint,
1291 1);
1292 histogram_tester_->ExpectTotalCount(
1293 internal::kHistogramParseStartToFirstMeaningfulPaint, 1);
1294 }
1295
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,FirstMeaningfulPaintNotRecorded)1296 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1297 FirstMeaningfulPaintNotRecorded) {
1298 ASSERT_TRUE(embedded_test_server()->Start());
1299
1300 auto waiter = CreatePageLoadMetricsTestWaiter();
1301 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
1302
1303 ui_test_utils::NavigateToURL(
1304 browser(), embedded_test_server()->GetURL(
1305 "/page_load_metrics/page_with_active_connections.html"));
1306 waiter->Wait();
1307
1308 // Navigate away before a FMP is reported.
1309 NavigateToUntrackedUrl();
1310
1311 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
1312 1);
1313 histogram_tester_->ExpectUniqueSample(
1314 internal::kHistogramFirstMeaningfulPaintStatus,
1315 internal::FIRST_MEANINGFUL_PAINT_DID_NOT_REACH_NETWORK_STABLE, 1);
1316 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstMeaningfulPaint,
1317 0);
1318 histogram_tester_->ExpectTotalCount(
1319 internal::kHistogramParseStartToFirstMeaningfulPaint, 0);
1320 }
1321
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PayloadSize)1322 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PayloadSize) {
1323 ASSERT_TRUE(embedded_test_server()->Start());
1324
1325 auto waiter = CreatePageLoadMetricsTestWaiter();
1326 waiter->AddPageExpectation(TimingField::kLoadEvent);
1327 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL(
1328 "/page_load_metrics/large.html"));
1329 waiter->Wait();
1330
1331 // Payload histograms are only logged when a page load terminates, so force
1332 // navigation to another page.
1333 NavigateToUntrackedUrl();
1334
1335 histogram_tester_->ExpectTotalCount(internal::kHistogramPageLoadTotalBytes,
1336 1);
1337
1338 // Verify that there is a single sample recorded in the 10kB bucket (the size
1339 // of the main HTML response).
1340 histogram_tester_->ExpectBucketCount(internal::kHistogramPageLoadTotalBytes,
1341 10, 1);
1342 }
1343
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PayloadSizeChildFrame)1344 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PayloadSizeChildFrame) {
1345 ASSERT_TRUE(embedded_test_server()->Start());
1346
1347 auto waiter = CreatePageLoadMetricsTestWaiter();
1348 waiter->AddPageExpectation(TimingField::kLoadEvent);
1349 ui_test_utils::NavigateToURL(
1350 browser(),
1351 embedded_test_server()->GetURL("/page_load_metrics/large_iframe.html"));
1352 waiter->Wait();
1353
1354 // Payload histograms are only logged when a page load terminates, so force
1355 // navigation to another page.
1356 NavigateToUntrackedUrl();
1357
1358 histogram_tester_->ExpectTotalCount(internal::kHistogramPageLoadTotalBytes,
1359 1);
1360
1361 // Verify that there is a single sample recorded in the 10kB bucket (the size
1362 // of the iframe response).
1363 histogram_tester_->ExpectBucketCount(internal::kHistogramPageLoadTotalBytes,
1364 10, 1);
1365 }
1366
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PayloadSizeIgnoresDownloads)1367 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1368 PayloadSizeIgnoresDownloads) {
1369 ASSERT_TRUE(embedded_test_server()->Start());
1370
1371 content::DownloadTestObserverTerminal downloads_observer(
1372 content::BrowserContext::GetDownloadManager(browser()->profile()),
1373 1, // == wait_count (only waiting for "download-test1.lib").
1374 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
1375
1376 ui_test_utils::NavigateToURL(
1377 browser(), embedded_test_server()->GetURL(
1378 "/page_load_metrics/download_anchor_click.html"));
1379 downloads_observer.WaitForFinished();
1380
1381 NavigateToUntrackedUrl();
1382
1383 histogram_tester_->ExpectUniqueSample(internal::kHistogramPageLoadTotalBytes,
1384 0, 1);
1385 }
1386
1387 // Test UseCounter Features observed in the main frame are recorded, exactly
1388 // once per feature.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterFeaturesInMainFrame)1389 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1390 UseCounterFeaturesInMainFrame) {
1391 ASSERT_TRUE(embedded_test_server()->Start());
1392
1393 auto waiter = CreatePageLoadMetricsTestWaiter();
1394 waiter->AddPageExpectation(TimingField::kLoadEvent);
1395 ui_test_utils::NavigateToURL(
1396 browser(), embedded_test_server()->GetURL(
1397 "/page_load_metrics/use_counter_features.html"));
1398 waiter->Wait();
1399 NavigateToUntrackedUrl();
1400
1401 histogram_tester_->ExpectBucketCount(
1402 internal::kFeaturesHistogramName,
1403 static_cast<int32_t>(WebFeature::kTextWholeText), 1);
1404 histogram_tester_->ExpectBucketCount(
1405 internal::kFeaturesHistogramMainFrameName,
1406 static_cast<int32_t>(WebFeature::kTextWholeText), 1);
1407 histogram_tester_->ExpectBucketCount(
1408 internal::kFeaturesHistogramName,
1409 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
1410 histogram_tester_->ExpectBucketCount(
1411 internal::kFeaturesHistogramMainFrameName,
1412 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
1413 histogram_tester_->ExpectBucketCount(
1414 internal::kFeaturesHistogramName,
1415 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 1);
1416 histogram_tester_->ExpectBucketCount(
1417 internal::kFeaturesHistogramMainFrameName,
1418 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 1);
1419 histogram_tester_->ExpectBucketCount(
1420 internal::kFeaturesHistogramName,
1421 static_cast<int32_t>(
1422 WebFeature::kApplicationCacheManifestSelectSecureOrigin),
1423 1);
1424 histogram_tester_->ExpectBucketCount(
1425 internal::kFeaturesHistogramMainFrameName,
1426 static_cast<int32_t>(
1427 WebFeature::kApplicationCacheManifestSelectSecureOrigin),
1428 1);
1429 histogram_tester_->ExpectBucketCount(
1430 internal::kFeaturesHistogramName,
1431 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1432 histogram_tester_->ExpectBucketCount(
1433 internal::kFeaturesHistogramMainFrameName,
1434 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1435 }
1436
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterCSSPropertiesInMainFrame)1437 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1438 UseCounterCSSPropertiesInMainFrame) {
1439 ASSERT_TRUE(embedded_test_server()->Start());
1440
1441 auto waiter = CreatePageLoadMetricsTestWaiter();
1442 waiter->AddPageExpectation(TimingField::kLoadEvent);
1443 ui_test_utils::NavigateToURL(
1444 browser(), embedded_test_server()->GetURL(
1445 "/page_load_metrics/use_counter_features.html"));
1446 waiter->Wait();
1447 NavigateToUntrackedUrl();
1448
1449 // CSSPropertyID::kFontFamily
1450 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 6,
1451 1);
1452 // CSSPropertyID::kFontSize
1453 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 7,
1454 1);
1455 histogram_tester_->ExpectBucketCount(
1456 internal::kCssPropertiesHistogramName,
1457 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1458 }
1459
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterAnimatedCSSPropertiesInMainFrame)1460 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1461 UseCounterAnimatedCSSPropertiesInMainFrame) {
1462 ASSERT_TRUE(embedded_test_server()->Start());
1463
1464 auto waiter = CreatePageLoadMetricsTestWaiter();
1465 waiter->AddPageExpectation(TimingField::kLoadEvent);
1466 ui_test_utils::NavigateToURL(
1467 browser(), embedded_test_server()->GetURL(
1468 "/page_load_metrics/use_counter_features.html"));
1469 waiter->Wait();
1470 NavigateToUntrackedUrl();
1471
1472 // CSSPropertyID::kWidth
1473 histogram_tester_->ExpectBucketCount(
1474 internal::kAnimatedCssPropertiesHistogramName, 161, 1);
1475 // CSSPropertyID::kMarginLeft
1476 histogram_tester_->ExpectBucketCount(
1477 internal::kAnimatedCssPropertiesHistogramName, 91, 1);
1478 histogram_tester_->ExpectBucketCount(
1479 internal::kAnimatedCssPropertiesHistogramName,
1480 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1481 }
1482
1483 class PageLoadMetricsBrowserTestWithAutoupgradesDisabled
1484 : public PageLoadMetricsBrowserTest {
1485 public:
SetUpCommandLine(base::CommandLine * command_line)1486 void SetUpCommandLine(base::CommandLine* command_line) override {
1487 PageLoadMetricsBrowserTest::SetUpCommandLine(command_line);
1488 feature_list.InitAndDisableFeature(
1489 blink::features::kMixedContentAutoupgrade);
1490 }
1491
1492 private:
1493 base::test::ScopedFeatureList feature_list;
1494 };
1495
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,UseCounterFeaturesMixedContent)1496 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,
1497 UseCounterFeaturesMixedContent) {
1498 // UseCounterFeaturesInMainFrame loads the test file on a loopback
1499 // address. Loopback is treated as a secure origin in most ways, but it
1500 // doesn't count as mixed content when it loads http://
1501 // subresources. Therefore, this test loads the test file on a real HTTPS
1502 // server.
1503 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
1504 https_server.AddDefaultHandlers(GetChromeTestDataDir());
1505 ASSERT_TRUE(https_server.Start());
1506
1507 auto waiter = CreatePageLoadMetricsTestWaiter();
1508 waiter->AddPageExpectation(TimingField::kLoadEvent);
1509 ui_test_utils::NavigateToURL(
1510 browser(),
1511 https_server.GetURL("/page_load_metrics/use_counter_features.html"));
1512 waiter->Wait();
1513 NavigateToUntrackedUrl();
1514
1515 histogram_tester_->ExpectBucketCount(
1516 internal::kFeaturesHistogramName,
1517 static_cast<int32_t>(WebFeature::kMixedContentAudio), 1);
1518 histogram_tester_->ExpectBucketCount(
1519 internal::kFeaturesHistogramName,
1520 static_cast<int32_t>(WebFeature::kMixedContentImage), 1);
1521 histogram_tester_->ExpectBucketCount(
1522 internal::kFeaturesHistogramName,
1523 static_cast<int32_t>(WebFeature::kMixedContentVideo), 1);
1524 histogram_tester_->ExpectBucketCount(
1525 internal::kFeaturesHistogramName,
1526 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1527 }
1528
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,UseCounterCSSPropertiesMixedContent)1529 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,
1530 UseCounterCSSPropertiesMixedContent) {
1531 // UseCounterCSSPropertiesInMainFrame loads the test file on a loopback
1532 // address. Loopback is treated as a secure origin in most ways, but it
1533 // doesn't count as mixed content when it loads http://
1534 // subresources. Therefore, this test loads the test file on a real HTTPS
1535 // server.
1536 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
1537 https_server.AddDefaultHandlers(GetChromeTestDataDir());
1538 ASSERT_TRUE(https_server.Start());
1539
1540 auto waiter = CreatePageLoadMetricsTestWaiter();
1541 waiter->AddPageExpectation(TimingField::kLoadEvent);
1542 ui_test_utils::NavigateToURL(
1543 browser(),
1544 https_server.GetURL("/page_load_metrics/use_counter_features.html"));
1545 waiter->Wait();
1546 NavigateToUntrackedUrl();
1547
1548 // CSSPropertyID::kFontFamily
1549 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 6,
1550 1);
1551 // CSSPropertyID::kFontSize
1552 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 7,
1553 1);
1554 histogram_tester_->ExpectBucketCount(
1555 internal::kCssPropertiesHistogramName,
1556 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1557 }
1558
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,UseCounterAnimatedCSSPropertiesMixedContent)1559 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,
1560 UseCounterAnimatedCSSPropertiesMixedContent) {
1561 // UseCounterCSSPropertiesInMainFrame loads the test file on a loopback
1562 // address. Loopback is treated as a secure origin in most ways, but it
1563 // doesn't count as mixed content when it loads http://
1564 // subresources. Therefore, this test loads the test file on a real HTTPS
1565 // server.
1566 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
1567 https_server.AddDefaultHandlers(GetChromeTestDataDir());
1568 ASSERT_TRUE(https_server.Start());
1569
1570 auto waiter = CreatePageLoadMetricsTestWaiter();
1571 waiter->AddPageExpectation(TimingField::kLoadEvent);
1572 ui_test_utils::NavigateToURL(
1573 browser(),
1574 https_server.GetURL("/page_load_metrics/use_counter_features.html"));
1575 waiter->Wait();
1576 NavigateToUntrackedUrl();
1577
1578 // CSSPropertyID::kWidth
1579 histogram_tester_->ExpectBucketCount(
1580 internal::kAnimatedCssPropertiesHistogramName, 161, 1);
1581 // CSSPropertyID::kMarginLeft
1582 histogram_tester_->ExpectBucketCount(
1583 internal::kAnimatedCssPropertiesHistogramName, 91, 1);
1584 histogram_tester_->ExpectBucketCount(
1585 internal::kAnimatedCssPropertiesHistogramName,
1586 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1587 }
1588
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterFeaturesInNonSecureMainFrame)1589 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1590 UseCounterFeaturesInNonSecureMainFrame) {
1591 ASSERT_TRUE(embedded_test_server()->Start());
1592
1593 auto waiter = CreatePageLoadMetricsTestWaiter();
1594 waiter->AddPageExpectation(TimingField::kLoadEvent);
1595 ui_test_utils::NavigateToURL(
1596 browser(),
1597 embedded_test_server()->GetURL(
1598 "non-secure.test", "/page_load_metrics/use_counter_features.html"));
1599 MakeComponentFullscreen("testvideo");
1600 waiter->Wait();
1601 NavigateToUntrackedUrl();
1602
1603 histogram_tester_->ExpectBucketCount(
1604 internal::kFeaturesHistogramName,
1605 static_cast<int32_t>(WebFeature::kTextWholeText), 1);
1606 histogram_tester_->ExpectBucketCount(
1607 internal::kFeaturesHistogramMainFrameName,
1608 static_cast<int32_t>(WebFeature::kTextWholeText), 1);
1609 histogram_tester_->ExpectBucketCount(
1610 internal::kFeaturesHistogramName,
1611 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
1612 histogram_tester_->ExpectBucketCount(
1613 internal::kFeaturesHistogramMainFrameName,
1614 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
1615 histogram_tester_->ExpectBucketCount(
1616 internal::kFeaturesHistogramName,
1617 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 1);
1618 histogram_tester_->ExpectBucketCount(
1619 internal::kFeaturesHistogramMainFrameName,
1620 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 1);
1621 histogram_tester_->ExpectBucketCount(
1622 internal::kFeaturesHistogramName,
1623 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1624 histogram_tester_->ExpectBucketCount(
1625 internal::kFeaturesHistogramMainFrameName,
1626 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1627 histogram_tester_->ExpectBucketCount(
1628 internal::kFeaturesHistogramName,
1629 static_cast<int32_t>(WebFeature::kFullscreenInsecureOrigin), 1);
1630 histogram_tester_->ExpectBucketCount(
1631 internal::kFeaturesHistogramMainFrameName,
1632 static_cast<int32_t>(WebFeature::kFullscreenInsecureOrigin), 1);
1633 }
1634
1635 // Test UseCounter UKM features observed.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterUkmFeaturesLogged)1636 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1637 UseCounterUkmFeaturesLogged) {
1638 ASSERT_TRUE(embedded_test_server()->Start());
1639
1640 auto waiter = CreatePageLoadMetricsTestWaiter();
1641 waiter->AddPageExpectation(TimingField::kLoadEvent);
1642 GURL url = embedded_test_server()->GetURL(
1643 "/page_load_metrics/use_counter_features.html");
1644 ui_test_utils::NavigateToURL(browser(), url);
1645 MakeComponentFullscreen("testvideo");
1646 waiter->Wait();
1647 NavigateToUntrackedUrl();
1648
1649 const auto& entries = test_ukm_recorder_->GetEntriesByName(
1650 ukm::builders::Blink_UseCounter::kEntryName);
1651 EXPECT_THAT(entries, SizeIs(4));
1652 std::vector<int64_t> ukm_features;
1653 for (const auto* entry : entries) {
1654 test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, url);
1655 test_ukm_recorder_->ExpectEntryMetric(
1656 entry, ukm::builders::Blink_UseCounter::kIsMainFrameFeatureName, 1);
1657 const auto* metric = test_ukm_recorder_->GetEntryMetric(
1658 entry, ukm::builders::Blink_UseCounter::kFeatureName);
1659 DCHECK(metric);
1660 ukm_features.push_back(*metric);
1661 }
1662 EXPECT_THAT(
1663 ukm_features,
1664 UnorderedElementsAre(
1665 static_cast<int64_t>(WebFeature::kPageVisits),
1666 static_cast<int64_t>(WebFeature::kFullscreenSecureOrigin),
1667 static_cast<int64_t>(WebFeature::kNavigatorVibrate),
1668 static_cast<int64_t>(
1669 WebFeature::kApplicationCacheManifestSelectSecureOrigin)));
1670 }
1671
1672 // Test UseCounter UKM mixed content features observed.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,UseCounterUkmMixedContentFeaturesLogged)1673 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithAutoupgradesDisabled,
1674 UseCounterUkmMixedContentFeaturesLogged) {
1675 // As with UseCounterFeaturesMixedContent, load on a real HTTPS server to
1676 // trigger mixed content.
1677 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
1678 https_server.AddDefaultHandlers(GetChromeTestDataDir());
1679 ASSERT_TRUE(https_server.Start());
1680
1681 auto waiter = CreatePageLoadMetricsTestWaiter();
1682 waiter->AddPageExpectation(TimingField::kLoadEvent);
1683 GURL url =
1684 https_server.GetURL("/page_load_metrics/use_counter_features.html");
1685 ui_test_utils::NavigateToURL(browser(), url);
1686 MakeComponentFullscreen("testvideo");
1687 waiter->Wait();
1688 NavigateToUntrackedUrl();
1689
1690 const auto& entries = test_ukm_recorder_->GetEntriesByName(
1691 ukm::builders::Blink_UseCounter::kEntryName);
1692 EXPECT_THAT(entries, SizeIs(7));
1693 std::vector<int64_t> ukm_features;
1694 for (const auto* entry : entries) {
1695 test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, url);
1696 test_ukm_recorder_->ExpectEntryMetric(
1697 entry, ukm::builders::Blink_UseCounter::kIsMainFrameFeatureName, 1);
1698 const auto* metric = test_ukm_recorder_->GetEntryMetric(
1699 entry, ukm::builders::Blink_UseCounter::kFeatureName);
1700 DCHECK(metric);
1701 ukm_features.push_back(*metric);
1702 }
1703 EXPECT_THAT(ukm_features,
1704 UnorderedElementsAre(
1705 static_cast<int64_t>(WebFeature::kPageVisits),
1706 static_cast<int64_t>(WebFeature::kFullscreenSecureOrigin),
1707 static_cast<int64_t>(WebFeature::kNavigatorVibrate),
1708 static_cast<int64_t>(
1709 WebFeature::kApplicationCacheManifestSelectSecureOrigin),
1710 static_cast<int64_t>(WebFeature::kMixedContentImage),
1711 static_cast<int64_t>(WebFeature::kMixedContentAudio),
1712 static_cast<int64_t>(WebFeature::kMixedContentVideo)));
1713 }
1714
1715 // Test UseCounter Features observed in a child frame are recorded, exactly
1716 // once per feature.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterFeaturesInIframe)1717 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, UseCounterFeaturesInIframe) {
1718 ASSERT_TRUE(embedded_test_server()->Start());
1719
1720 auto waiter = CreatePageLoadMetricsTestWaiter();
1721 waiter->AddPageExpectation(TimingField::kLoadEvent);
1722 ui_test_utils::NavigateToURL(
1723 browser(), embedded_test_server()->GetURL(
1724 "/page_load_metrics/use_counter_features_in_iframe.html"));
1725 waiter->Wait();
1726 NavigateToUntrackedUrl();
1727
1728 histogram_tester_->ExpectBucketCount(
1729 internal::kFeaturesHistogramName,
1730 static_cast<int32_t>(WebFeature::kTextWholeText), 1);
1731 histogram_tester_->ExpectBucketCount(
1732 internal::kFeaturesHistogramName,
1733 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
1734 histogram_tester_->ExpectBucketCount(
1735 internal::kFeaturesHistogramName,
1736 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 1);
1737 histogram_tester_->ExpectBucketCount(
1738 internal::kFeaturesHistogramName,
1739 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1740 // No feature but page visits should get counted.
1741 histogram_tester_->ExpectBucketCount(
1742 internal::kFeaturesHistogramMainFrameName,
1743 static_cast<int32_t>(WebFeature::kTextWholeText), 0);
1744 histogram_tester_->ExpectBucketCount(
1745 internal::kFeaturesHistogramMainFrameName,
1746 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 0);
1747 histogram_tester_->ExpectBucketCount(
1748 internal::kFeaturesHistogramMainFrameName,
1749 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 0);
1750 histogram_tester_->ExpectBucketCount(
1751 internal::kFeaturesHistogramMainFrameName,
1752 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1753 }
1754
1755 // Test UseCounter Features observed in multiple child frames are recorded,
1756 // exactly once per feature.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterFeaturesInIframes)1757 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1758 UseCounterFeaturesInIframes) {
1759 ASSERT_TRUE(embedded_test_server()->Start());
1760
1761 auto waiter = CreatePageLoadMetricsTestWaiter();
1762 waiter->AddPageExpectation(TimingField::kLoadEvent);
1763 ui_test_utils::NavigateToURL(
1764 browser(),
1765 embedded_test_server()->GetURL(
1766 "/page_load_metrics/use_counter_features_in_iframes.html"));
1767 waiter->Wait();
1768 NavigateToUntrackedUrl();
1769
1770 histogram_tester_->ExpectBucketCount(
1771 internal::kFeaturesHistogramName,
1772 static_cast<int32_t>(WebFeature::kTextWholeText), 1);
1773 histogram_tester_->ExpectBucketCount(
1774 internal::kFeaturesHistogramName,
1775 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 1);
1776 histogram_tester_->ExpectBucketCount(
1777 internal::kFeaturesHistogramName,
1778 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 1);
1779 histogram_tester_->ExpectBucketCount(
1780 internal::kFeaturesHistogramName,
1781 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1782 // No feature but page visits should get counted.
1783 histogram_tester_->ExpectBucketCount(
1784 internal::kFeaturesHistogramMainFrameName,
1785 static_cast<int32_t>(WebFeature::kTextWholeText), 0);
1786 histogram_tester_->ExpectBucketCount(
1787 internal::kFeaturesHistogramMainFrameName,
1788 static_cast<int32_t>(WebFeature::kV8Element_Animate_Method), 0);
1789 histogram_tester_->ExpectBucketCount(
1790 internal::kFeaturesHistogramMainFrameName,
1791 static_cast<int32_t>(WebFeature::kNavigatorVibrate), 0);
1792 histogram_tester_->ExpectBucketCount(
1793 internal::kFeaturesHistogramMainFrameName,
1794 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1795 }
1796
1797 // Test UseCounter CSS properties observed in a child frame are recorded,
1798 // exactly once per feature.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterCSSPropertiesInIframe)1799 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1800 UseCounterCSSPropertiesInIframe) {
1801 ASSERT_TRUE(embedded_test_server()->Start());
1802
1803 auto waiter = CreatePageLoadMetricsTestWaiter();
1804 waiter->AddPageExpectation(TimingField::kLoadEvent);
1805 ui_test_utils::NavigateToURL(
1806 browser(), embedded_test_server()->GetURL(
1807 "/page_load_metrics/use_counter_features_in_iframe.html"));
1808 waiter->Wait();
1809 NavigateToUntrackedUrl();
1810
1811 // CSSPropertyID::kFontFamily
1812 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 6,
1813 1);
1814 // CSSPropertyID::kFontSize
1815 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 7,
1816 1);
1817 histogram_tester_->ExpectBucketCount(
1818 internal::kCssPropertiesHistogramName,
1819 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1820 }
1821
1822 // Test UseCounter CSS Properties observed in multiple child frames are
1823 // recorded, exactly once per feature.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterCSSPropertiesInIframes)1824 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1825 UseCounterCSSPropertiesInIframes) {
1826 ASSERT_TRUE(embedded_test_server()->Start());
1827
1828 auto waiter = CreatePageLoadMetricsTestWaiter();
1829 waiter->AddPageExpectation(TimingField::kLoadEvent);
1830 ui_test_utils::NavigateToURL(
1831 browser(),
1832 embedded_test_server()->GetURL(
1833 "/page_load_metrics/use_counter_features_in_iframes.html"));
1834 waiter->Wait();
1835 NavigateToUntrackedUrl();
1836
1837 // CSSPropertyID::kFontFamily
1838 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 6,
1839 1);
1840 // CSSPropertyID::kFontSize
1841 histogram_tester_->ExpectBucketCount(internal::kCssPropertiesHistogramName, 7,
1842 1);
1843 histogram_tester_->ExpectBucketCount(
1844 internal::kCssPropertiesHistogramName,
1845 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1846 }
1847
1848 // Test UseCounter CSS properties observed in a child frame are recorded,
1849 // exactly once per feature.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterAnimatedCSSPropertiesInIframe)1850 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1851 UseCounterAnimatedCSSPropertiesInIframe) {
1852 ASSERT_TRUE(embedded_test_server()->Start());
1853
1854 auto waiter = CreatePageLoadMetricsTestWaiter();
1855 waiter->AddPageExpectation(TimingField::kLoadEvent);
1856 ui_test_utils::NavigateToURL(
1857 browser(), embedded_test_server()->GetURL(
1858 "/page_load_metrics/use_counter_features_in_iframe.html"));
1859 waiter->Wait();
1860 NavigateToUntrackedUrl();
1861
1862 // CSSPropertyID::kWidth
1863 histogram_tester_->ExpectBucketCount(
1864 internal::kAnimatedCssPropertiesHistogramName, 161, 1);
1865 // CSSPropertyID::kMarginLeft
1866 histogram_tester_->ExpectBucketCount(
1867 internal::kAnimatedCssPropertiesHistogramName, 91, 1);
1868 histogram_tester_->ExpectBucketCount(
1869 internal::kAnimatedCssPropertiesHistogramName,
1870 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1871 }
1872
1873 // Test UseCounter CSS Properties observed in multiple child frames are
1874 // recorded, exactly once per feature.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterAnimatedCSSPropertiesInIframes)1875 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1876 UseCounterAnimatedCSSPropertiesInIframes) {
1877 ASSERT_TRUE(embedded_test_server()->Start());
1878
1879 auto waiter = CreatePageLoadMetricsTestWaiter();
1880 waiter->AddPageExpectation(TimingField::kLoadEvent);
1881 ui_test_utils::NavigateToURL(
1882 browser(),
1883 embedded_test_server()->GetURL(
1884 "/page_load_metrics/use_counter_features_in_iframes.html"));
1885 waiter->Wait();
1886 NavigateToUntrackedUrl();
1887
1888 // CSSPropertyID::kWidth
1889 histogram_tester_->ExpectBucketCount(
1890 internal::kAnimatedCssPropertiesHistogramName, 161, 1);
1891 // CSSPropertyID::kMarginLeft
1892 histogram_tester_->ExpectBucketCount(
1893 internal::kAnimatedCssPropertiesHistogramName, 91, 1);
1894 histogram_tester_->ExpectBucketCount(
1895 internal::kAnimatedCssPropertiesHistogramName,
1896 blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
1897 }
1898
1899 // Test UseCounter Features observed for SVG pages.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,UseCounterObserveSVGImagePage)1900 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
1901 UseCounterObserveSVGImagePage) {
1902 ASSERT_TRUE(embedded_test_server()->Start());
1903
1904 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL(
1905 "/page_load_metrics/circle.svg"));
1906 NavigateToUntrackedUrl();
1907
1908 histogram_tester_->ExpectBucketCount(
1909 internal::kFeaturesHistogramName,
1910 static_cast<int32_t>(WebFeature::kPageVisits), 1);
1911 }
1912
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,LoadingMetrics)1913 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, LoadingMetrics) {
1914 ASSERT_TRUE(embedded_test_server()->Start());
1915 auto waiter = CreatePageLoadMetricsTestWaiter();
1916 waiter->AddPageExpectation(TimingField::kLoadTimingInfo);
1917 ui_test_utils::NavigateToURL(browser(),
1918 embedded_test_server()->GetURL("/title1.html"));
1919 // Waits until nonzero loading metrics are seen.
1920 waiter->Wait();
1921 }
1922
1923 class SessionRestorePageLoadMetricsBrowserTest
1924 : public PageLoadMetricsBrowserTest {
1925 public:
SessionRestorePageLoadMetricsBrowserTest()1926 SessionRestorePageLoadMetricsBrowserTest() {}
1927
1928 // PageLoadMetricsBrowserTest:
SetUpOnMainThread()1929 void SetUpOnMainThread() override {
1930 PageLoadMetricsBrowserTest::SetUpOnMainThread();
1931 ASSERT_TRUE(embedded_test_server()->Start());
1932 }
1933
QuitBrowserAndRestore(Browser * browser)1934 Browser* QuitBrowserAndRestore(Browser* browser) {
1935 Profile* profile = browser->profile();
1936
1937 SessionStartupPref::SetStartupPref(
1938 profile, SessionStartupPref(SessionStartupPref::LAST));
1939 #if defined(OS_CHROMEOS)
1940 SessionServiceTestHelper helper(
1941 SessionServiceFactory::GetForProfile(profile));
1942 helper.SetForceBrowserNotAliveWithNoWindows(true);
1943 helper.ReleaseService();
1944 #endif
1945
1946 std::unique_ptr<ScopedKeepAlive> keep_alive(new ScopedKeepAlive(
1947 KeepAliveOrigin::SESSION_RESTORE, KeepAliveRestartOption::DISABLED));
1948 CloseBrowserSynchronously(browser);
1949
1950 // Create a new window, which should trigger session restore.
1951 chrome::NewEmptyWindow(profile);
1952 SessionRestoreTestHelper().Wait();
1953 return BrowserList::GetInstance()->GetLastActive();
1954 }
1955
WaitForTabsToLoad(Browser * browser)1956 void WaitForTabsToLoad(Browser* browser) {
1957 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
1958 content::WebContents* contents =
1959 browser->tab_strip_model()->GetWebContentsAt(i);
1960 contents->GetController().LoadIfNecessary();
1961 ASSERT_TRUE(content::WaitForLoadStop(contents));
1962 }
1963 }
1964
1965 // The PageLoadMetricsTestWaiter can observe first meaningful paints on these
1966 // test pages while not on other simple pages such as /title1.html.
GetTestURL() const1967 GURL GetTestURL() const {
1968 return embedded_test_server()->GetURL(
1969 "/page_load_metrics/main_frame_with_iframe.html");
1970 }
1971
GetTestURL2() const1972 GURL GetTestURL2() const {
1973 return embedded_test_server()->GetURL("/title2.html");
1974 }
1975
ExpectFirstPaintMetricsTotalCount(int expected_total_count) const1976 void ExpectFirstPaintMetricsTotalCount(int expected_total_count) const {
1977 histogram_tester_->ExpectTotalCount(
1978 internal::kHistogramSessionRestoreForegroundTabFirstPaint,
1979 expected_total_count);
1980 histogram_tester_->ExpectTotalCount(
1981 internal::kHistogramSessionRestoreForegroundTabFirstContentfulPaint,
1982 expected_total_count);
1983 histogram_tester_->ExpectTotalCount(
1984 internal::kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint,
1985 expected_total_count);
1986 }
1987
1988 private:
1989 DISALLOW_COPY_AND_ASSIGN(SessionRestorePageLoadMetricsBrowserTest);
1990 };
1991
1992 class SessionRestorePaintWaiter : public SessionRestoreObserver {
1993 public:
SessionRestorePaintWaiter()1994 SessionRestorePaintWaiter() { SessionRestore::AddObserver(this); }
~SessionRestorePaintWaiter()1995 ~SessionRestorePaintWaiter() { SessionRestore::RemoveObserver(this); }
1996
1997 // SessionRestoreObserver implementation:
OnWillRestoreTab(content::WebContents * contents)1998 void OnWillRestoreTab(content::WebContents* contents) override {
1999 chrome::InitializePageLoadMetricsForWebContents(contents);
2000 auto waiter = std::make_unique<PageLoadMetricsTestWaiter>(contents);
2001 waiter->AddPageExpectation(TimingField::kFirstPaint);
2002 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2003 waiter->AddPageExpectation(TimingField::kFirstMeaningfulPaint);
2004 waiters_[contents] = std::move(waiter);
2005 }
2006
2007 // First meaningful paints occur only on foreground tabs.
WaitForForegroundTabs(size_t num_expected_foreground_tabs)2008 void WaitForForegroundTabs(size_t num_expected_foreground_tabs) {
2009 size_t num_actual_foreground_tabs = 0;
2010 for (auto iter = waiters_.begin(); iter != waiters_.end(); ++iter) {
2011 if (iter->first->GetVisibility() == content::Visibility::HIDDEN)
2012 continue;
2013 iter->second->Wait();
2014 ++num_actual_foreground_tabs;
2015 }
2016 EXPECT_EQ(num_expected_foreground_tabs, num_actual_foreground_tabs);
2017 }
2018
2019 private:
2020 std::unordered_map<content::WebContents*,
2021 std::unique_ptr<PageLoadMetricsTestWaiter>>
2022 waiters_;
2023
2024 DISALLOW_COPY_AND_ASSIGN(SessionRestorePaintWaiter);
2025 };
2026
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,InitialVisibilityOfSingleRestoredTab)2027 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2028 InitialVisibilityOfSingleRestoredTab) {
2029 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2030 histogram_tester_->ExpectTotalCount(
2031 page_load_metrics::internal::kPageLoadStartedInForeground, 1);
2032 histogram_tester_->ExpectBucketCount(
2033 page_load_metrics::internal::kPageLoadStartedInForeground, true, 1);
2034
2035 Browser* new_browser = QuitBrowserAndRestore(browser());
2036 ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser));
2037
2038 histogram_tester_->ExpectTotalCount(
2039 page_load_metrics::internal::kPageLoadStartedInForeground, 2);
2040 histogram_tester_->ExpectBucketCount(
2041 page_load_metrics::internal::kPageLoadStartedInForeground, true, 2);
2042 }
2043
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,InitialVisibilityOfMultipleRestoredTabs)2044 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2045 InitialVisibilityOfMultipleRestoredTabs) {
2046 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2047 ui_test_utils::NavigateToURLWithDisposition(
2048 browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
2049 ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
2050 histogram_tester_->ExpectTotalCount(
2051 page_load_metrics::internal::kPageLoadStartedInForeground, 2);
2052 histogram_tester_->ExpectBucketCount(
2053 page_load_metrics::internal::kPageLoadStartedInForeground, false, 1);
2054
2055 Browser* new_browser = QuitBrowserAndRestore(browser());
2056 ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser));
2057
2058 TabStripModel* tab_strip = new_browser->tab_strip_model();
2059 ASSERT_TRUE(tab_strip);
2060 ASSERT_EQ(2, tab_strip->count());
2061
2062 histogram_tester_->ExpectTotalCount(
2063 page_load_metrics::internal::kPageLoadStartedInForeground, 4);
2064 histogram_tester_->ExpectBucketCount(
2065 page_load_metrics::internal::kPageLoadStartedInForeground, true, 2);
2066 histogram_tester_->ExpectBucketCount(
2067 page_load_metrics::internal::kPageLoadStartedInForeground, false, 2);
2068 }
2069
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,NoSessionRestore)2070 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2071 NoSessionRestore) {
2072 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2073 ExpectFirstPaintMetricsTotalCount(0);
2074 }
2075
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,SingleTabSessionRestore)2076 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2077 SingleTabSessionRestore) {
2078 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2079
2080 SessionRestorePaintWaiter session_restore_paint_waiter;
2081 QuitBrowserAndRestore(browser());
2082
2083 session_restore_paint_waiter.WaitForForegroundTabs(1);
2084 ExpectFirstPaintMetricsTotalCount(1);
2085 }
2086
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,MultipleTabsSessionRestore)2087 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2088 MultipleTabsSessionRestore) {
2089 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2090 ui_test_utils::NavigateToURLWithDisposition(
2091 browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
2092 ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
2093
2094 SessionRestorePaintWaiter session_restore_paint_waiter;
2095 Browser* new_browser = QuitBrowserAndRestore(browser());
2096
2097 TabStripModel* tab_strip = new_browser->tab_strip_model();
2098 ASSERT_TRUE(tab_strip);
2099 ASSERT_EQ(2, tab_strip->count());
2100
2101 // Only metrics of the initial foreground tab are recorded.
2102 session_restore_paint_waiter.WaitForForegroundTabs(1);
2103 ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser));
2104 ExpectFirstPaintMetricsTotalCount(1);
2105 }
2106
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,NavigationDuringSessionRestore)2107 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2108 NavigationDuringSessionRestore) {
2109 NavigateToUntrackedUrl();
2110 Browser* new_browser = QuitBrowserAndRestore(browser());
2111
2112 auto waiter = std::make_unique<PageLoadMetricsTestWaiter>(
2113 new_browser->tab_strip_model()->GetActiveWebContents());
2114 waiter->AddPageExpectation(TimingField::kFirstMeaningfulPaint);
2115 ui_test_utils::NavigateToURL(new_browser, GetTestURL());
2116 waiter->Wait();
2117
2118 // No metrics recorded for the second navigation because the tab navigated
2119 // away during session restore.
2120 ExpectFirstPaintMetricsTotalCount(0);
2121 }
2122
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,LoadingAfterSessionRestore)2123 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2124 LoadingAfterSessionRestore) {
2125 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2126
2127 Browser* new_browser = nullptr;
2128 {
2129 SessionRestorePaintWaiter session_restore_paint_waiter;
2130 new_browser = QuitBrowserAndRestore(browser());
2131
2132 session_restore_paint_waiter.WaitForForegroundTabs(1);
2133 ExpectFirstPaintMetricsTotalCount(1);
2134 }
2135
2136 // Load a new page after session restore.
2137 auto waiter = std::make_unique<PageLoadMetricsTestWaiter>(
2138 new_browser->tab_strip_model()->GetActiveWebContents());
2139 waiter->AddPageExpectation(TimingField::kFirstMeaningfulPaint);
2140 ui_test_utils::NavigateToURL(new_browser, GetTestURL());
2141 waiter->Wait();
2142
2143 // No more metrics because the navigation is after session restore.
2144 ExpectFirstPaintMetricsTotalCount(1);
2145 }
2146
2147 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
2148 #define MAYBE_InitialForegroundTabChanged DISABLED_InitialForegroundTabChanged
2149 #else
2150 #define MAYBE_InitialForegroundTabChanged InitialForegroundTabChanged
2151 #endif
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,MAYBE_InitialForegroundTabChanged)2152 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2153 MAYBE_InitialForegroundTabChanged) {
2154 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2155 ui_test_utils::NavigateToURLWithDisposition(
2156 browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
2157 ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
2158
2159 SessionRestorePaintWaiter session_restore_paint_waiter;
2160 Browser* new_browser = QuitBrowserAndRestore(browser());
2161
2162 // Change the foreground tab before the first meaningful paint.
2163 TabStripModel* tab_strip = new_browser->tab_strip_model();
2164 ASSERT_TRUE(tab_strip);
2165 ASSERT_EQ(2, tab_strip->count());
2166 ASSERT_EQ(0, tab_strip->active_index());
2167 tab_strip->ActivateTabAt(1, {TabStripModel::GestureType::kOther});
2168
2169 session_restore_paint_waiter.WaitForForegroundTabs(1);
2170
2171 // No metrics were recorded because initial foreground tab was switched away.
2172 ExpectFirstPaintMetricsTotalCount(0);
2173 }
2174
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,MultipleSessionRestores)2175 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2176 MultipleSessionRestores) {
2177 ui_test_utils::NavigateToURL(browser(), GetTestURL());
2178
2179 Browser* current_browser = browser();
2180 const int num_session_restores = 3;
2181 for (int i = 1; i <= num_session_restores; ++i) {
2182 SessionRestorePaintWaiter session_restore_paint_waiter;
2183 current_browser = QuitBrowserAndRestore(current_browser);
2184 session_restore_paint_waiter.WaitForForegroundTabs(1);
2185 ExpectFirstPaintMetricsTotalCount(i);
2186 }
2187 }
2188
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,RestoreForeignTab)2189 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2190 RestoreForeignTab) {
2191 sessions::SessionTab tab;
2192 tab.tab_visual_index = 0;
2193 tab.current_navigation_index = 1;
2194 tab.navigations.push_back(sessions::ContentTestHelper::CreateNavigation(
2195 GetTestURL().spec(), "one"));
2196 tab.navigations.back().set_encoded_page_state("");
2197
2198 ASSERT_EQ(1, browser()->tab_strip_model()->count());
2199
2200 // Restore in the current tab.
2201 content::WebContents* tab_contents = nullptr;
2202 {
2203 SessionRestorePaintWaiter session_restore_paint_waiter;
2204 tab_contents = SessionRestore::RestoreForeignSessionTab(
2205 browser()->tab_strip_model()->GetActiveWebContents(), tab,
2206 WindowOpenDisposition::CURRENT_TAB);
2207 ASSERT_EQ(1, browser()->tab_strip_model()->count());
2208 ASSERT_TRUE(tab_contents);
2209 ASSERT_EQ(GetTestURL(), tab_contents->GetURL());
2210
2211 session_restore_paint_waiter.WaitForForegroundTabs(1);
2212 ExpectFirstPaintMetricsTotalCount(1);
2213 }
2214
2215 // Restore in a new foreground tab.
2216 {
2217 SessionRestorePaintWaiter session_restore_paint_waiter;
2218 tab_contents = SessionRestore::RestoreForeignSessionTab(
2219 browser()->tab_strip_model()->GetActiveWebContents(), tab,
2220 WindowOpenDisposition::NEW_FOREGROUND_TAB);
2221 ASSERT_EQ(2, browser()->tab_strip_model()->count());
2222 ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
2223 ASSERT_TRUE(tab_contents);
2224 ASSERT_EQ(GetTestURL(), tab_contents->GetURL());
2225
2226 session_restore_paint_waiter.WaitForForegroundTabs(1);
2227 ExpectFirstPaintMetricsTotalCount(2);
2228 }
2229
2230 // Restore in a new background tab.
2231 {
2232 tab_contents = SessionRestore::RestoreForeignSessionTab(
2233 browser()->tab_strip_model()->GetActiveWebContents(), tab,
2234 WindowOpenDisposition::NEW_BACKGROUND_TAB);
2235 ASSERT_EQ(3, browser()->tab_strip_model()->count());
2236 ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
2237 ASSERT_TRUE(tab_contents);
2238 ASSERT_EQ(GetTestURL(), tab_contents->GetURL());
2239 ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(browser()));
2240
2241 // Do not record timings of initially background tabs.
2242 ExpectFirstPaintMetricsTotalCount(2);
2243 }
2244 }
2245
IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,RestoreForeignSession)2246 IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
2247 RestoreForeignSession) {
2248 Profile* profile = browser()->profile();
2249
2250 // Set up the restore data: one window with two tabs.
2251 std::vector<const sessions::SessionWindow*> session;
2252 sessions::SessionWindow window;
2253 {
2254 auto tab1 = std::make_unique<sessions::SessionTab>();
2255 tab1->tab_visual_index = 0;
2256 tab1->current_navigation_index = 0;
2257 tab1->pinned = true;
2258 tab1->navigations.push_back(sessions::ContentTestHelper::CreateNavigation(
2259 GetTestURL().spec(), "one"));
2260 tab1->navigations.back().set_encoded_page_state("");
2261 window.tabs.push_back(std::move(tab1));
2262 }
2263
2264 {
2265 auto tab2 = std::make_unique<sessions::SessionTab>();
2266 tab2->tab_visual_index = 1;
2267 tab2->current_navigation_index = 0;
2268 tab2->pinned = false;
2269 tab2->navigations.push_back(sessions::ContentTestHelper::CreateNavigation(
2270 GetTestURL2().spec(), "two"));
2271 tab2->navigations.back().set_encoded_page_state("");
2272 window.tabs.push_back(std::move(tab2));
2273 }
2274
2275 // Restore the session window with 2 tabs.
2276 session.push_back(static_cast<const sessions::SessionWindow*>(&window));
2277 SessionRestorePaintWaiter session_restore_paint_waiter;
2278 SessionRestore::RestoreForeignSessionWindows(profile, session.begin(),
2279 session.end());
2280 session_restore_paint_waiter.WaitForForegroundTabs(1);
2281
2282 Browser* new_browser = BrowserList::GetInstance()->GetLastActive();
2283 ASSERT_TRUE(new_browser);
2284 ASSERT_EQ(2, new_browser->tab_strip_model()->count());
2285
2286 ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser));
2287 ExpectFirstPaintMetricsTotalCount(1);
2288 }
2289
2290 // TODO(crbug.com/882077) Disabled due to flaky timeouts on all platforms.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DISABLED_ReceivedAggregateResourceDataLength)2291 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2292 DISABLED_ReceivedAggregateResourceDataLength) {
2293 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2294 content::SetupCrossSiteRedirector(embedded_test_server());
2295 ASSERT_TRUE(embedded_test_server()->Start());
2296
2297 auto waiter = CreatePageLoadMetricsTestWaiter();
2298 waiter->AddPageExpectation(TimingField::kLoadEvent);
2299 ui_test_utils::NavigateToURL(
2300 browser(), embedded_test_server()->GetURL(
2301 "foo.com", "/cross_site_iframe_factory.html?foo"));
2302 waiter->Wait();
2303 int64_t one_frame_page_size = waiter->current_network_bytes();
2304
2305 waiter = CreatePageLoadMetricsTestWaiter();
2306 waiter->AddPageExpectation(TimingField::kLoadEvent);
2307 ui_test_utils::NavigateToURL(
2308 browser(),
2309 embedded_test_server()->GetURL(
2310 "a.com", "/cross_site_iframe_factory.html?a(b,c,d(e,f,g))"));
2311 // Verify that 7 iframes are fetched, with some amount of tolerance since
2312 // favicon is fetched only once.
2313 waiter->AddMinimumNetworkBytesExpectation(7 * (one_frame_page_size - 100));
2314 waiter->Wait();
2315 }
2316
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,ChunkedResponse_OverheadDoesNotCountForBodyBytes)2317 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2318 ChunkedResponse_OverheadDoesNotCountForBodyBytes) {
2319 const char kHttpResponseHeader[] =
2320 "HTTP/1.1 200 OK\r\n"
2321 "Content-Type: text/html; charset=utf-8\r\n"
2322 "Transfer-Encoding: chunked\r\n"
2323 "\r\n";
2324 const int kChunkSize = 5;
2325 const int kNumChunks = 5;
2326 auto main_response =
2327 std::make_unique<net::test_server::ControllableHttpResponse>(
2328 embedded_test_server(), "/mock_page.html",
2329 true /*relative_url_is_prefix*/);
2330 ASSERT_TRUE(embedded_test_server()->Start());
2331
2332 auto waiter = CreatePageLoadMetricsTestWaiter();
2333
2334 browser()->OpenURL(content::OpenURLParams(
2335 embedded_test_server()->GetURL("/mock_page.html"), content::Referrer(),
2336 WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
2337
2338 main_response->WaitForRequest();
2339 main_response->Send(kHttpResponseHeader);
2340 for (int i = 0; i < kNumChunks; i++) {
2341 main_response->Send(std::to_string(kChunkSize));
2342 main_response->Send("\r\n");
2343 main_response->Send(std::string(kChunkSize, '*'));
2344 main_response->Send("\r\n");
2345 }
2346 main_response->Done();
2347 waiter->AddMinimumCompleteResourcesExpectation(1);
2348 waiter->Wait();
2349
2350 // Verify that overheads for each chunk are not reported as body bytes.
2351 EXPECT_EQ(waiter->current_network_body_bytes(), kChunkSize * kNumChunks);
2352 }
2353
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,ReceivedCompleteResources)2354 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ReceivedCompleteResources) {
2355 const char kHttpResponseHeader[] =
2356 "HTTP/1.1 200 OK\r\n"
2357 "Content-Type: text/html; charset=utf-8\r\n"
2358 "\r\n";
2359 auto main_html_response =
2360 std::make_unique<net::test_server::ControllableHttpResponse>(
2361 embedded_test_server(), "/mock_page.html",
2362 true /*relative_url_is_prefix*/);
2363 auto script_response =
2364 std::make_unique<net::test_server::ControllableHttpResponse>(
2365 embedded_test_server(), "/script.js",
2366 true /*relative_url_is_prefix*/);
2367 auto iframe_response =
2368 std::make_unique<net::test_server::ControllableHttpResponse>(
2369 embedded_test_server(), "/iframe.html",
2370 true /*relative_url_is_prefix*/);
2371 ASSERT_TRUE(embedded_test_server()->Start());
2372
2373 auto waiter = CreatePageLoadMetricsTestWaiter();
2374
2375 browser()->OpenURL(content::OpenURLParams(
2376 embedded_test_server()->GetURL("/mock_page.html"), content::Referrer(),
2377 WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
2378
2379 main_html_response->WaitForRequest();
2380 main_html_response->Send(kHttpResponseHeader);
2381 main_html_response->Send(
2382 "<html><body></body><script src=\"script.js\"></script></html>");
2383 main_html_response->Send(std::string(1000, ' '));
2384 main_html_response->Done();
2385 waiter->AddMinimumCompleteResourcesExpectation(1);
2386 waiter->AddMinimumNetworkBytesExpectation(1000);
2387 waiter->Wait();
2388
2389 script_response->WaitForRequest();
2390 script_response->Send(kHttpResponseHeader);
2391 script_response->Send(
2392 "var iframe = document.createElement(\"iframe\");"
2393 "iframe.src =\"iframe.html\";"
2394 "document.body.appendChild(iframe);");
2395 script_response->Send(std::string(1000, ' '));
2396 // Data received but resource not complete
2397 waiter->AddMinimumCompleteResourcesExpectation(1);
2398 waiter->AddMinimumNetworkBytesExpectation(2000);
2399 waiter->Wait();
2400 script_response->Done();
2401 waiter->AddMinimumCompleteResourcesExpectation(2);
2402 waiter->Wait();
2403
2404 // Make sure main resources are loaded correctly
2405 iframe_response->WaitForRequest();
2406 iframe_response->Send(kHttpResponseHeader);
2407 iframe_response->Send(std::string(2000, ' '));
2408 iframe_response->Done();
2409 waiter->AddMinimumCompleteResourcesExpectation(3);
2410 waiter->AddMinimumNetworkBytesExpectation(4000);
2411 waiter->Wait();
2412 }
2413
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MemoryCacheResource_Recorded)2414 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2415 MemoryCacheResource_Recorded) {
2416 const char kHttpResponseHeader[] =
2417 "HTTP/1.1 200 OK\r\n"
2418 "Content-Type: text/html; charset=utf-8\r\n"
2419 "Cache-Control: max-age=60\r\n"
2420 "\r\n";
2421 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2422 content::SetupCrossSiteRedirector(embedded_test_server());
2423 auto cached_response =
2424 std::make_unique<net::test_server::ControllableHttpResponse>(
2425 embedded_test_server(), "/cachetime",
2426 true /*relative_url_is_prefix*/);
2427 ASSERT_TRUE(embedded_test_server()->Start());
2428
2429 auto waiter = CreatePageLoadMetricsTestWaiter();
2430 browser()->OpenURL(content::OpenURLParams(
2431 embedded_test_server()->GetURL("/page_with_cached_subresource.html"),
2432 content::Referrer(), WindowOpenDisposition::CURRENT_TAB,
2433 ui::PAGE_TRANSITION_TYPED, false));
2434
2435 // Load a resource large enough to record a nonzero number of kilobytes.
2436 cached_response->WaitForRequest();
2437 cached_response->Send(kHttpResponseHeader);
2438 cached_response->Send(std::string(10 * 1024, ' '));
2439 cached_response->Done();
2440
2441 waiter->AddMinimumCompleteResourcesExpectation(3);
2442 waiter->Wait();
2443
2444 // Re-navigate the page to the same url with a different query string so the
2445 // main resource is not loaded from the disk cache. The subresource will be
2446 // loaded from the memory cache.
2447 waiter = CreatePageLoadMetricsTestWaiter();
2448 browser()->OpenURL(content::OpenURLParams(
2449 embedded_test_server()->GetURL("/page_with_cached_subresource.html?xyz"),
2450 content::Referrer(), WindowOpenDisposition::CURRENT_TAB,
2451 ui::PAGE_TRANSITION_TYPED, false));
2452
2453 // Favicon is not fetched this time.
2454 waiter->AddMinimumCompleteResourcesExpectation(2);
2455 waiter->Wait();
2456
2457 // Verify no resources were cached for the first load.
2458 histogram_tester_->ExpectBucketCount(
2459 internal::kHistogramCacheCompletedResources, 0, 1);
2460 histogram_tester_->ExpectBucketCount(internal::kHistogramPageLoadCacheBytes,
2461 0, 1);
2462
2463 // Force histograms to record.
2464 NavigateToUntrackedUrl();
2465
2466 // Verify that the cached resource from the memory cache is recorded
2467 // correctly.
2468 histogram_tester_->ExpectBucketCount(
2469 internal::kHistogramCacheCompletedResources, 1, 1);
2470 histogram_tester_->ExpectBucketCount(internal::kHistogramPageLoadCacheBytes,
2471 10, 1);
2472 }
2473
2474 // Verifies that css image resources shared across document do not cause a
2475 // crash, and are only counted once per context. https://crbug.com/979459.
2476 // TODO(crbug.com/1108534): Disabled due to flakiness.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,DISABLED_MemoryCacheResources_RecordedOncePerContext)2477 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2478 DISABLED_MemoryCacheResources_RecordedOncePerContext) {
2479 embedded_test_server()->ServeFilesFromSourceDirectory("chrome/test/data");
2480 content::SetupCrossSiteRedirector(embedded_test_server());
2481 ASSERT_TRUE(embedded_test_server()->Start());
2482
2483 auto waiter = CreatePageLoadMetricsTestWaiter();
2484 ui_test_utils::NavigateToURL(
2485 browser(),
2486 embedded_test_server()->GetURL(
2487 "/page_load_metrics/document_with_css_image_sharing.html"));
2488
2489 waiter->AddMinimumCompleteResourcesExpectation(7);
2490 waiter->Wait();
2491
2492 // Force histograms to record.
2493 NavigateToUntrackedUrl();
2494
2495 // Verify that cached resources are only reported once per context.
2496 histogram_tester_->ExpectBucketCount(
2497 internal::kHistogramCacheCompletedResources, 2, 1);
2498 }
2499
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,InputEventsForClick)2500 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, InputEventsForClick) {
2501 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2502 content::SetupCrossSiteRedirector(embedded_test_server());
2503 ASSERT_TRUE(embedded_test_server()->Start());
2504
2505 auto waiter = CreatePageLoadMetricsTestWaiter();
2506 waiter->AddPageExpectation(TimingField::kLoadEvent);
2507 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2508 GURL url = embedded_test_server()->GetURL("/page_load_metrics/link.html");
2509 ui_test_utils::NavigateToURL(browser(), url);
2510 waiter->Wait();
2511 content::SimulateMouseClickAt(
2512 browser()->tab_strip_model()->GetActiveWebContents(), 0,
2513 blink::WebMouseEvent::Button::kLeft, gfx::Point(100, 100));
2514 waiter = CreatePageLoadMetricsTestWaiter();
2515 waiter->AddPageExpectation(TimingField::kLoadEvent);
2516 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2517 waiter->Wait();
2518
2519 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToNavigation, 1);
2520 histogram_tester_->ExpectTotalCount(
2521 internal::kHistogramInputToNavigationLinkClick, 1);
2522 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToFirstPaint, 1);
2523 histogram_tester_->ExpectTotalCount(
2524 internal::kHistogramInputToFirstContentfulPaint, 1);
2525
2526 // Force navigation to another page, which should force logging of histograms
2527 // persisted at the end of the page load lifetime.
2528 NavigateToUntrackedUrl();
2529
2530 // Navigation should record the metrics twice because of the initial pageload
2531 // and the second pageload ("/title1.html") initiated by the link click.
2532 VerifyNavigationMetrics(
2533 {url, embedded_test_server()->GetURL("/title1.html")});
2534 }
2535
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,InputEventsForOmniboxMatch)2536 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, InputEventsForOmniboxMatch) {
2537 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2538 content::SetupCrossSiteRedirector(embedded_test_server());
2539 ASSERT_TRUE(embedded_test_server()->Start());
2540
2541 auto waiter = CreatePageLoadMetricsTestWaiter();
2542 waiter->AddPageExpectation(TimingField::kLoadEvent);
2543 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2544 GURL url = embedded_test_server()->GetURL("/title1.html");
2545 ui_test_utils::SendToOmniboxAndSubmit(browser(), url.spec(),
2546 base::TimeTicks::Now());
2547 waiter->Wait();
2548
2549 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToNavigation, 1);
2550 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToFirstPaint, 1);
2551 histogram_tester_->ExpectTotalCount(
2552 internal::kHistogramInputToFirstContentfulPaint, 1);
2553
2554 // Force navigation to another page, which should force logging of histograms
2555 // persisted at the end of the page load lifetime.
2556 NavigateToUntrackedUrl();
2557
2558 VerifyNavigationMetrics({url});
2559 }
2560
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,InputEventsForJavaScriptHref)2561 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2562 InputEventsForJavaScriptHref) {
2563 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2564 content::SetupCrossSiteRedirector(embedded_test_server());
2565 ASSERT_TRUE(embedded_test_server()->Start());
2566
2567 auto waiter = CreatePageLoadMetricsTestWaiter();
2568 waiter->AddPageExpectation(TimingField::kLoadEvent);
2569 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2570 GURL url =
2571 embedded_test_server()->GetURL("/page_load_metrics/javascript_href.html");
2572 ui_test_utils::NavigateToURL(browser(), url);
2573 waiter->Wait();
2574 waiter = CreatePageLoadMetricsTestWaiter();
2575 content::SimulateMouseClickAt(
2576 browser()->tab_strip_model()->GetActiveWebContents(), 0,
2577 blink::WebMouseEvent::Button::kLeft, gfx::Point(100, 100));
2578 waiter->AddPageExpectation(TimingField::kLoadEvent);
2579 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2580 waiter->Wait();
2581
2582 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToNavigation, 1);
2583 histogram_tester_->ExpectTotalCount(
2584 internal::kHistogramInputToNavigationLinkClick, 1);
2585 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToFirstPaint, 1);
2586 histogram_tester_->ExpectTotalCount(
2587 internal::kHistogramInputToFirstContentfulPaint, 1);
2588
2589 // Force navigation to another page, which should force logging of histograms
2590 // persisted at the end of the page load lifetime.
2591 NavigateToUntrackedUrl();
2592
2593 // Navigation should record the metrics twice because of the initial pageload
2594 // and the second pageload ("/title1.html") initiated by the link click.
2595 VerifyNavigationMetrics(
2596 {url, embedded_test_server()->GetURL("/title1.html")});
2597 }
2598
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,InputEventsForJavaScriptWindowOpen)2599 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2600 InputEventsForJavaScriptWindowOpen) {
2601 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2602 content::SetupCrossSiteRedirector(embedded_test_server());
2603 ASSERT_TRUE(embedded_test_server()->Start());
2604
2605 auto waiter = CreatePageLoadMetricsTestWaiter();
2606 waiter->AddPageExpectation(TimingField::kLoadEvent);
2607 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2608 GURL url = embedded_test_server()->GetURL(
2609 "/page_load_metrics/javascript_window_open.html");
2610 ui_test_utils::NavigateToURL(browser(), url);
2611 waiter->Wait();
2612 content::WebContentsAddedObserver web_contents_added_observer;
2613 content::SimulateMouseClickAt(
2614 browser()->tab_strip_model()->GetActiveWebContents(), 0,
2615 blink::WebMouseEvent::Button::kLeft, gfx::Point(100, 100));
2616 // Wait for new window to open.
2617 auto* web_contents = web_contents_added_observer.GetWebContents();
2618 waiter = std::make_unique<PageLoadMetricsTestWaiter>(web_contents);
2619 waiter->AddPageExpectation(TimingField::kLoadEvent);
2620 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2621 waiter->Wait();
2622
2623 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToNavigation, 1);
2624 histogram_tester_->ExpectTotalCount(
2625 internal::kHistogramInputToNavigationLinkClick, 1);
2626 histogram_tester_->ExpectTotalCount(internal::kHistogramInputToFirstPaint, 1);
2627 histogram_tester_->ExpectTotalCount(
2628 internal::kHistogramInputToFirstContentfulPaint, 1);
2629
2630 // Close all pages, which should force logging of histograms persisted at the
2631 // end of the page load lifetime.
2632 browser()->tab_strip_model()->CloseAllTabs();
2633
2634 // Navigation should record the metrics twice because of the initial pageload
2635 // and the second pageload ("/title1.html") initiated by the link click.
2636 VerifyNavigationMetrics(
2637 {url, embedded_test_server()->GetURL("/title1.html")});
2638 }
2639
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,FirstInputFromScroll)2640 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, FirstInputFromScroll) {
2641 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2642 content::SetupCrossSiteRedirector(embedded_test_server());
2643 ASSERT_TRUE(embedded_test_server()->Start());
2644
2645 auto waiter = CreatePageLoadMetricsTestWaiter();
2646 waiter->AddPageExpectation(TimingField::kLoadEvent);
2647 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2648 ui_test_utils::NavigateToURL(
2649 browser(),
2650 embedded_test_server()->GetURL("/page_load_metrics/scroll.html"));
2651 waiter->Wait();
2652
2653 content::SimulateGestureScrollSequence(
2654 browser()->tab_strip_model()->GetActiveWebContents(),
2655 gfx::Point(100, 100), gfx::Vector2dF(0, 15));
2656 NavigateToUntrackedUrl();
2657
2658 // First Input Delay should not be reported from a scroll!
2659 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstInputDelay, 0);
2660 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstInputTimestamp,
2661 0);
2662 }
2663
2664 // Does a navigation to a page controlled by a service worker and verifies
2665 // that service worker page load metrics are logged.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,ServiceWorkerMetrics)2666 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ServiceWorkerMetrics) {
2667 ASSERT_TRUE(embedded_test_server()->Start());
2668
2669 auto waiter = CreatePageLoadMetricsTestWaiter();
2670 waiter->AddPageExpectation(TimingField::kFirstPaint);
2671
2672 // Load a page that registers a service worker.
2673 GURL url = embedded_test_server()->GetURL(
2674 "/service_worker/create_service_worker.html");
2675 ui_test_utils::NavigateToURL(browser(), url);
2676 EXPECT_EQ("DONE", EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
2677 "register('fetch_event_pass_through.js');"));
2678 waiter->Wait();
2679
2680 // The first load was not controlled, so service worker metrics should not be
2681 // logged.
2682 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 1);
2683 histogram_tester_->ExpectTotalCount(
2684 internal::kHistogramServiceWorkerFirstPaint, 0);
2685
2686 waiter = CreatePageLoadMetricsTestWaiter();
2687 waiter->AddPageExpectation(TimingField::kFirstPaint);
2688
2689 // Load a controlled page.
2690 GURL controlled_url = url;
2691 ui_test_utils::NavigateToURL(browser(), controlled_url);
2692 waiter->Wait();
2693
2694 // Service worker metrics should be logged.
2695 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstPaint, 2);
2696 histogram_tester_->ExpectTotalCount(
2697 internal::kHistogramServiceWorkerFirstPaint, 1);
2698
2699 // Force navigation to another page, which should force logging of histograms
2700 // persisted at the end of the page load lifetime.
2701 NavigateToUntrackedUrl();
2702
2703 // Navigation should record the metrics twice because of the initial pageload
2704 // to register a service worker and the page load controlled by the service
2705 // worker.
2706 VerifyNavigationMetrics({url, controlled_url});
2707 }
2708
2709 // Does a navigation to a page which records a WebFeature before commit.
2710 // Regression test for https://crbug.com/1043018.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PreCommitWebFeature)2711 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PreCommitWebFeature) {
2712 ASSERT_TRUE(embedded_test_server()->Start());
2713
2714 auto waiter = CreatePageLoadMetricsTestWaiter();
2715 waiter->AddPageExpectation(TimingField::kLoadEvent);
2716
2717 ui_test_utils::NavigateToURL(browser(),
2718 embedded_test_server()->GetURL("/title1.html"));
2719 waiter->Wait();
2720
2721 histogram_tester_->ExpectBucketCount(
2722 internal::kFeaturesHistogramName,
2723 static_cast<int32_t>(WebFeature::kSecureContextCheckPassed), 1);
2724 histogram_tester_->ExpectBucketCount(
2725 internal::kFeaturesHistogramName,
2726 static_cast<int32_t>(WebFeature::kSecureContextCheckFailed), 0);
2727 }
2728
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MainFrameIntersectionsMainFrame)2729 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2730 MainFrameIntersectionsMainFrame) {
2731 ASSERT_TRUE(embedded_test_server()->Start());
2732
2733 auto waiter = CreatePageLoadMetricsTestWaiter();
2734 content::WebContents* web_contents =
2735 browser()->tab_strip_model()->GetActiveWebContents();
2736
2737 // Evaluate the height and width of the page as the browser_test can
2738 // vary the dimensions.
2739 int document_height =
2740 EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
2741 int document_width =
2742 EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
2743
2744 // Expectation is before NavigateToUrl for this test as the expectation can be
2745 // met after NavigateToUrl and before the Wait.
2746 waiter->AddMainFrameIntersectionExpectation(
2747 gfx::Rect(0, 0, document_width,
2748 document_height)); // Initial main frame rect.
2749
2750 ui_test_utils::NavigateToURL(
2751 browser(),
2752 embedded_test_server()->GetURL(
2753 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2754 waiter->Wait();
2755
2756 // Create a |document_width|x|document_height| frame at 100,100, increasing
2757 // the page width and height by 100.
2758 waiter->AddMainFrameIntersectionExpectation(
2759 gfx::Rect(0, 0, document_width + 100, document_height + 100));
2760 EXPECT_TRUE(ExecJs(
2761 web_contents,
2762 content::JsReplace("createIframeAtRect(\"test\", 100, 100, $1, $2);",
2763 document_width, document_height)));
2764 waiter->Wait();
2765 }
2766
2767 // Creates a single frame within the main frame and verifies the intersection
2768 // with the main frame.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MainFrameIntersectionSingleFrame)2769 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2770 MainFrameIntersectionSingleFrame) {
2771 ASSERT_TRUE(embedded_test_server()->Start());
2772
2773 auto waiter = CreatePageLoadMetricsTestWaiter();
2774 ui_test_utils::NavigateToURL(
2775 browser(),
2776 embedded_test_server()->GetURL(
2777 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2778 content::WebContents* web_contents =
2779 browser()->tab_strip_model()->GetActiveWebContents();
2780
2781 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 200, 200));
2782
2783 // Create a 200x200 iframe at 100,100.
2784 EXPECT_TRUE(ExecJs(web_contents,
2785 "createIframeAtRect(\"test\", 100, 100, 200, 200);"));
2786
2787 waiter->Wait();
2788 }
2789
2790 // Creates a set of nested frames within the main frame and verifies
2791 // their intersections with the main frame.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MainFrameIntersectionSameOrigin)2792 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2793 MainFrameIntersectionSameOrigin) {
2794 EXPECT_TRUE(embedded_test_server()->Start());
2795
2796 auto waiter = CreatePageLoadMetricsTestWaiter();
2797 ui_test_utils::NavigateToURL(
2798 browser(),
2799 embedded_test_server()->GetURL(
2800 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2801 content::WebContents* web_contents =
2802 browser()->tab_strip_model()->GetActiveWebContents();
2803
2804 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 200, 200));
2805
2806 // Create a 200x200 iframe at 100,100.
2807 EXPECT_TRUE(ExecJs(web_contents,
2808 "createIframeAtRect(\"test\", 100, 100, 200, 200);"));
2809 waiter->Wait();
2810
2811 NavigateIframeToURL(
2812 web_contents, "test",
2813 embedded_test_server()->GetURL(
2814 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2815
2816 // Creates the grandchild iframe within the child frame at 10, 10 with
2817 // dimensions 300x300. This frame is clipped by 110 pixels in the bottom and
2818 // right. This translates to an intersection of 110, 110, 190, 190 with the
2819 // main frame.
2820 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(110, 110, 190, 190));
2821 content::RenderFrameHost* child_frame =
2822 content::ChildFrameAt(web_contents->GetMainFrame(), 0);
2823 EXPECT_TRUE(
2824 ExecJs(child_frame, "createIframeAtRect(\"test2\", 10, 10, 300, 300);"));
2825
2826 waiter->Wait();
2827 }
2828
2829 // Creates a set of nested frames, with a cross origin subframe, within the
2830 // main frame and verifies their intersections with the main frame.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MainFrameIntersectionCrossOrigin)2831 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2832 MainFrameIntersectionCrossOrigin) {
2833 EXPECT_TRUE(embedded_test_server()->Start());
2834 auto waiter = CreatePageLoadMetricsTestWaiter();
2835 ui_test_utils::NavigateToURL(
2836 browser(),
2837 embedded_test_server()->GetURL(
2838 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2839 content::WebContents* web_contents =
2840 browser()->tab_strip_model()->GetActiveWebContents();
2841
2842 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 200, 200));
2843
2844 // Create a 200x200 iframe at 100,100.
2845 EXPECT_TRUE(ExecJs(web_contents,
2846 "createIframeAtRect(\"test\", 100, 100, 200, 200);"));
2847
2848 NavigateIframeToURL(
2849 web_contents, "test",
2850 embedded_test_server()->GetURL(
2851 "b.com",
2852 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2853
2854 // Wait for the main frame intersection after we have navigated the frame
2855 // to a cross-origin url.
2856 waiter->Wait();
2857
2858 // Change the size of the frame to 150, 150. This tests the cross origin
2859 // code path as the previous wait can flakily pass due to receiving the
2860 // correct intersection before the frame transitions to cross-origin without
2861 // checking that the final computation is consistent.
2862 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 150, 150));
2863 EXPECT_TRUE(ExecJs(web_contents,
2864 "let frame = document.getElementById('test'); "
2865 "frame.width = 150; "
2866 "frame.height = 150; "));
2867 waiter->Wait();
2868
2869 // Creates the grandchild iframe within the child frame at 10, 10 with
2870 // dimensions 300x300. This frame is clipped by 110 pixels in the bottom and
2871 // right. This translates to an intersection of 110, 110, 190, 190 with the
2872 // main frame.
2873 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(110, 110, 140, 140));
2874 content::RenderFrameHost* child_frame =
2875 content::ChildFrameAt(web_contents->GetMainFrame(), 0);
2876 EXPECT_TRUE(
2877 ExecJs(child_frame, "createIframeAtRect(\"test2\", 10, 10, 300, 300);"));
2878
2879 waiter->Wait();
2880 }
2881
2882 // Creates a set of nested frames, with a cross origin subframe that is out of
2883 // view within the main frame and verifies their intersections with the main
2884 // frame.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MainFrameIntersectionCrossOriginOutOfView)2885 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2886 MainFrameIntersectionCrossOriginOutOfView) {
2887 EXPECT_TRUE(embedded_test_server()->Start());
2888 auto waiter = CreatePageLoadMetricsTestWaiter();
2889 ui_test_utils::NavigateToURL(
2890 browser(),
2891 embedded_test_server()->GetURL(
2892 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2893 content::WebContents* web_contents =
2894 browser()->tab_strip_model()->GetActiveWebContents();
2895
2896 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 200, 200));
2897
2898 // Create a 200x200 iframe at 100,100.
2899 EXPECT_TRUE(ExecJs(web_contents,
2900 "createIframeAtRect(\"test\", 100, 100, 200, 200);"));
2901
2902 NavigateIframeToURL(
2903 web_contents, "test",
2904 embedded_test_server()->GetURL(
2905 "b.com",
2906 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2907
2908 // Wait for the main frame intersection after we have navigated the frame
2909 // to a cross-origin url.
2910 waiter->Wait();
2911
2912 // Creates the grandchild iframe within the child frame outside the parent
2913 // frame's viewport.
2914 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(0, 0, 0, 0));
2915 content::RenderFrameHost* child_frame =
2916 content::ChildFrameAt(web_contents->GetMainFrame(), 0);
2917 EXPECT_TRUE(ExecJs(child_frame,
2918 "createIframeAtRect(\"test2\", 5000, 5000, 190, 190);"));
2919
2920 waiter->Wait();
2921 }
2922
2923 // Creates a set of nested frames, with a cross origin subframe that is out of
2924 // view within the main frame and verifies their intersections with the main
2925 // frame. The out of view frame is then scrolled back into view and the
2926 // intersection is verified.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,MainFrameIntersectionCrossOriginScrolled)2927 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
2928 MainFrameIntersectionCrossOriginScrolled) {
2929 EXPECT_TRUE(embedded_test_server()->Start());
2930 auto waiter = CreatePageLoadMetricsTestWaiter();
2931 ui_test_utils::NavigateToURL(
2932 browser(),
2933 embedded_test_server()->GetURL(
2934 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2935 content::WebContents* web_contents =
2936 browser()->tab_strip_model()->GetActiveWebContents();
2937
2938 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 200, 200));
2939
2940 // Create a 200x200 iframe at 100,100.
2941 EXPECT_TRUE(ExecJs(web_contents,
2942 "createIframeAtRect(\"test\", 100, 100, 200, 200);"));
2943
2944 NavigateIframeToURL(
2945 web_contents, "test",
2946 embedded_test_server()->GetURL(
2947 "b.com",
2948 "/page_load_metrics/blank_with_positioned_iframe_writer.html"));
2949
2950 // Wait for the main frame intersection after we have navigated the frame
2951 // to a cross-origin url.
2952 waiter->Wait();
2953
2954 // Creates the grandchild iframe within the child frame outside the parent
2955 // frame's viewport.
2956 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(0, 0, 0, 0));
2957 content::RenderFrameHost* child_frame =
2958 content::ChildFrameAt(web_contents->GetMainFrame(), 0);
2959 EXPECT_TRUE(ExecJs(child_frame,
2960 "createIframeAtRect(\"test2\", 5000, 5000, 190, 190);"));
2961 waiter->Wait();
2962
2963 // Scroll the child frame and verify the grandchild frame's intersection.
2964 // The parent frame is at position 100,100 with dimensions 200x200. The
2965 // child frame after scrolling is positioned at 100,100 within the parent
2966 // frame and is clipped to 100x100. The grand child's main frame document
2967 // position is then 200,200 after the child frame is scrolled.
2968 waiter->AddMainFrameIntersectionExpectation(gfx::Rect(200, 200, 100, 100));
2969
2970 EXPECT_TRUE(ExecJs(child_frame, "window.scroll(4900, 4900); "));
2971
2972 waiter->Wait();
2973 }
2974
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PageLCPStopsUponInput)2975 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PageLCPStopsUponInput) {
2976 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
2977 content::SetupCrossSiteRedirector(embedded_test_server());
2978 ASSERT_TRUE(embedded_test_server()->Start());
2979
2980 // Waiter to ensure main content is loaded.
2981 auto waiter = CreatePageLoadMetricsTestWaiter();
2982 waiter->AddPageExpectation(TimingField::kLoadEvent);
2983 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
2984 waiter->AddPageExpectation(TimingField::kLargestContentfulPaint);
2985
2986 // Waiter to ensure that iframe content is loaded.
2987 auto waiter2 = CreatePageLoadMetricsTestWaiter();
2988 waiter2->AddPageExpectation(TimingField::kLoadEvent);
2989 waiter2->AddSubFrameExpectation(TimingField::kLoadEvent);
2990 waiter2->AddPageExpectation(TimingField::kFirstContentfulPaint);
2991 waiter2->AddSubFrameExpectation(TimingField::kFirstContentfulPaint);
2992 waiter2->AddPageExpectation(TimingField::kLargestContentfulPaint);
2993 waiter2->AddSubFrameExpectation(TimingField::kLargestContentfulPaint);
2994 waiter2->AddPageExpectation(TimingField::kFirstInputOrScroll);
2995
2996 ui_test_utils::NavigateToURL(
2997 browser(), embedded_test_server()->GetURL(
2998 "/page_load_metrics/click_to_create_iframe.html"));
2999 waiter->Wait();
3000
3001 // Tap in the middle of the button.
3002 ASSERT_TRUE(content::ExecuteScriptWithoutUserGesture(
3003 RenderFrameHost(),
3004 "var submitRect = document.getElementById('button')"
3005 ".getBoundingClientRect();"));
3006 double y;
3007 ASSERT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractDouble(
3008 RenderFrameHost(),
3009 "window.domAutomationController.send((submitRect.top +"
3010 "submitRect.bottom) / 2);",
3011 &y));
3012 double x;
3013 EXPECT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractDouble(
3014 RenderFrameHost(),
3015 "window.domAutomationController.send((submitRect.left + submitRect.right)"
3016 "/ 2);",
3017 &x));
3018 content::SimulateMouseClickAt(
3019 browser()->tab_strip_model()->GetActiveWebContents(), 0,
3020 blink::WebMouseEvent::Button::kLeft,
3021 gfx::Point(static_cast<int>(x), static_cast<int>(y)));
3022 waiter2->Wait();
3023
3024 // LCP is collected only at the end of the page lifecycle. Navigate to flush.
3025 NavigateToUntrackedUrl();
3026
3027 histogram_tester_->ExpectTotalCount(
3028 internal::kHistogramLargestContentfulPaint, 1);
3029 auto all_frames_value =
3030 histogram_tester_
3031 ->GetAllSamples(internal::kHistogramLargestContentfulPaint)[0]
3032 .min;
3033
3034 histogram_tester_->ExpectTotalCount(
3035 internal::kHistogramLargestContentfulPaintMainFrame, 1);
3036 auto main_frame_value =
3037 histogram_tester_
3038 ->GetAllSamples(
3039 internal::kHistogramLargestContentfulPaintMainFrame)[0]
3040 .min;
3041 // Even though the content on the iframe is larger, the all_frames LCP value
3042 // should match the main frame value because the iframe content was created
3043 // after input in the main frame.
3044 ASSERT_EQ(all_frames_value, main_frame_value);
3045 }
3046
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,FirstInputDelayFromClick)3047 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, FirstInputDelayFromClick) {
3048 ASSERT_TRUE(embedded_test_server()->Start());
3049
3050 auto waiter = CreatePageLoadMetricsTestWaiter();
3051 waiter->AddPageExpectation(TimingField::kLoadEvent);
3052 waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
3053
3054 auto waiter2 = CreatePageLoadMetricsTestWaiter();
3055 waiter2->AddPageExpectation(TimingField::kLoadEvent);
3056 waiter2->AddPageExpectation(TimingField::kFirstContentfulPaint);
3057 waiter2->AddPageExpectation(TimingField::kFirstInputDelay);
3058 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL(
3059 "/page_load_metrics/click.html"));
3060 waiter->Wait();
3061 content::SimulateMouseClickAt(
3062 browser()->tab_strip_model()->GetActiveWebContents(), 0,
3063 blink::WebMouseEvent::Button::kLeft, gfx::Point(100, 100));
3064 waiter2->Wait();
3065
3066 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstInputDelay, 1);
3067 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstInputTimestamp,
3068 1);
3069 }
3070
3071 // Tests that a portal activation records metrics.
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,PortalActivation)3072 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PortalActivation) {
3073 // We only record metrics for portals when the time is consistent across
3074 // processes.
3075 if (!base::TimeTicks::IsConsistentAcrossProcesses())
3076 return;
3077
3078 ASSERT_TRUE(embedded_test_server()->Start());
3079 ui_test_utils::NavigateToURL(
3080 browser(), embedded_test_server()->GetURL("portal.test", "/title1.html"));
3081 content::WebContents* outer_contents =
3082 browser()->tab_strip_model()->GetActiveWebContents();
3083
3084 // Create a portal to a.com.
3085 GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
3086 std::string script = R"(
3087 var portal = document.createElement('portal');
3088 portal.src = '%s';
3089 document.body.appendChild(portal);
3090 )";
3091 content::WebContentsAddedObserver contents_observer;
3092 content::TestNavigationObserver portal_nav_observer(a_url);
3093 portal_nav_observer.StartWatchingNewWebContents();
3094 EXPECT_TRUE(ExecJs(outer_contents,
3095 base::StringPrintf(script.c_str(), a_url.spec().c_str())));
3096 portal_nav_observer.WaitForNavigationFinished();
3097 content::WebContents* portal_contents = contents_observer.GetWebContents();
3098
3099 {
3100 // The portal is not activated, so nothing should be recorded.
3101 auto entries = test_ukm_recorder_->GetMergedEntriesByName(
3102 ukm::builders::PageLoad::kEntryName);
3103 EXPECT_EQ(0u, entries.size());
3104 }
3105
3106 // Activate the portal.
3107 std::string activated_listener = R"(
3108 activatePromise = new Promise(resolve => {
3109 window.addEventListener('portalactivate', resolve(true));
3110 });
3111 )";
3112 EXPECT_TRUE(ExecJs(portal_contents, activated_listener));
3113 EXPECT_TRUE(
3114 ExecJs(outer_contents, "document.querySelector('portal').activate()"));
3115
3116 EXPECT_EQ(true,
3117 EvalJsWithManualReply(portal_contents,
3118 "activatePromise.then(r => { "
3119 " window.domAutomationController.send(r);"
3120 "});"));
3121
3122 // The activated portal contents should be the currently active contents.
3123 EXPECT_EQ(portal_contents,
3124 browser()->tab_strip_model()->GetActiveWebContents());
3125 EXPECT_NE(portal_contents, outer_contents);
3126
3127 {
3128 // The portal is activated, so there should be a PageLoad entry.
3129 auto entries = test_ukm_recorder_->GetMergedEntriesByName(
3130 ukm::builders::PageLoad::kEntryName);
3131 EXPECT_EQ(1u, entries.size());
3132 }
3133 {
3134 // The portal is activated, also check the portal entry.
3135 auto entries = test_ukm_recorder_->GetMergedEntriesByName(
3136 ukm::builders::Portal_Activate::kEntryName);
3137 EXPECT_EQ(1u, entries.size());
3138 }
3139 }
3140
3141 class PageLoadMetricsBrowserTestWithBackForwardCache
3142 : public PageLoadMetricsBrowserTest {
3143 public:
SetUpCommandLine(base::CommandLine * command_line)3144 void SetUpCommandLine(base::CommandLine* command_line) override {
3145 PageLoadMetricsBrowserTest::SetUpCommandLine(command_line);
3146 feature_list.InitAndEnableFeatureWithParameters(
3147 features::kBackForwardCache,
3148 // Set a very long TTL before expiration (longer than the test timeout)
3149 // so tests that are expecting deletion don't pass when they shouldn't.
3150 //
3151 // TODO(hajimehoshi): This value is used in various places. Define a
3152 // constant and use it.
3153 //
3154 // Some features like the outstanding network requests are expected to
3155 // appear in almost any output. Filter them out to make the tests
3156 // simpler.
3157 {{"TimeToLiveInBackForwardCacheInSeconds", "3600"},
3158 {"ignore_outstanding_network_request_for_testing", "true"}});
3159 }
3160
3161 private:
3162 base::test::ScopedFeatureList feature_list;
3163 };
3164
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithBackForwardCache,BackForwardCacheEvent)3165 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestWithBackForwardCache,
3166 BackForwardCacheEvent) {
3167 ASSERT_TRUE(embedded_test_server()->Start());
3168
3169 auto url1 = embedded_test_server()->GetURL("a.com", "/title1.html");
3170 auto url2 = embedded_test_server()->GetURL("b.com", "/title1.html");
3171
3172 // Go to URL1.
3173 ui_test_utils::NavigateToURL(browser(), url1);
3174
3175 histogram_tester_->ExpectBucketCount(
3176 internal::kHistogramBackForwardCacheEvent,
3177 internal::PageLoadBackForwardCacheEvent::kEnterBackForwardCache, 0);
3178 histogram_tester_->ExpectBucketCount(
3179 internal::kHistogramBackForwardCacheEvent,
3180 internal::PageLoadBackForwardCacheEvent::kRestoreFromBackForwardCache, 0);
3181
3182 // Go to URL2. The previous page (URL1) is put into the back-forward cache.
3183 ui_test_utils::NavigateToURL(browser(), url2);
3184
3185 histogram_tester_->ExpectBucketCount(
3186 internal::kHistogramBackForwardCacheEvent,
3187 internal::PageLoadBackForwardCacheEvent::kEnterBackForwardCache, 1);
3188 histogram_tester_->ExpectBucketCount(
3189 internal::kHistogramBackForwardCacheEvent,
3190 internal::PageLoadBackForwardCacheEvent::kRestoreFromBackForwardCache, 0);
3191
3192 // Go back to URL1. The previous page (URL2) is put into the back-forward
3193 // cache.
3194 content::WebContents* web_contents =
3195 browser()->tab_strip_model()->GetActiveWebContents();
3196 web_contents->GetController().GoBack();
3197 EXPECT_TRUE(WaitForLoadStop(web_contents));
3198
3199 histogram_tester_->ExpectBucketCount(
3200 internal::kHistogramBackForwardCacheEvent,
3201 internal::PageLoadBackForwardCacheEvent::kEnterBackForwardCache, 2);
3202
3203 // For now UmaPageLoadMetricsObserver::OnEnterBackForwardCache returns
3204 // STOP_OBSERVING, OnRestoreFromBackForward is never reached.
3205 //
3206 // TODO(hajimehoshi): Update this when the UmaPageLoadMetricsObserver
3207 // continues to observe after entering to back-forward cache.
3208 histogram_tester_->ExpectBucketCount(
3209 internal::kHistogramBackForwardCacheEvent,
3210 internal::PageLoadBackForwardCacheEvent::kRestoreFromBackForwardCache, 0);
3211 }
3212
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,EarlyHints)3213 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, EarlyHints) {
3214 content::NavigationHandleTiming timing =
3215 NavigateWithEarlyHints(EarlyHintsPolicy::OneHint);
3216
3217 // There were no redirections, so the first request should be the same as the
3218 // final request.
3219 EXPECT_FALSE(timing.early_hints_for_first_request_time.is_null());
3220 EXPECT_FALSE(timing.early_hints_for_final_request_time.is_null());
3221 EXPECT_EQ(timing.early_hints_for_first_request_time,
3222 timing.early_hints_for_final_request_time);
3223
3224 // The timings of the Early Hints response should be recorded.
3225 histogram_tester_->ExpectTotalCount(
3226 internal::kHistogramEarlyHintsFirstRequestStartToEarlyHints, 1);
3227 histogram_tester_->ExpectTotalCount(
3228 internal::kHistogramEarlyHintsFinalRequestStartToEarlyHints, 1);
3229 histogram_tester_->ExpectTotalCount(
3230 internal::kHistogramEarlyHintsEarlyHintsToFinalResponseStart, 1);
3231
3232 using NavigationTiming = ukm::builders::NavigationTiming;
3233 const auto& entries =
3234 test_ukm_recorder_->GetMergedEntriesByName(NavigationTiming::kEntryName);
3235 EXPECT_EQ(1u, entries.size());
3236 for (const auto& kv : entries) {
3237 test_ukm_recorder_->ExpectEntrySourceHasUrl(
3238 kv.second.get(), embedded_test_server()->GetURL("/mock_page.html"));
3239 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3240 kv.second.get(), NavigationTiming::kEarlyHintsForFirstRequestName));
3241 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3242 kv.second.get(), NavigationTiming::kEarlyHintsForFinalRequestName));
3243 }
3244 }
3245
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,EarlyHints_NoHints)3246 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, EarlyHints_NoHints) {
3247 content::NavigationHandleTiming timing =
3248 NavigateWithEarlyHints(EarlyHintsPolicy::NoHints);
3249
3250 // No Early Hints responses were received.
3251 EXPECT_TRUE(timing.early_hints_for_first_request_time.is_null());
3252 EXPECT_TRUE(timing.early_hints_for_final_request_time.is_null());
3253
3254 // The timings of the Early Hints response should not be recorded.
3255 histogram_tester_->ExpectTotalCount(
3256 internal::kHistogramEarlyHintsFirstRequestStartToEarlyHints, 0);
3257 histogram_tester_->ExpectTotalCount(
3258 internal::kHistogramEarlyHintsFinalRequestStartToEarlyHints, 0);
3259 histogram_tester_->ExpectTotalCount(
3260 internal::kHistogramEarlyHintsEarlyHintsToFinalResponseStart, 0);
3261
3262 using NavigationTiming = ukm::builders::NavigationTiming;
3263 const auto& entries =
3264 test_ukm_recorder_->GetMergedEntriesByName(NavigationTiming::kEntryName);
3265 EXPECT_EQ(1u, entries.size());
3266 for (const auto& kv : entries) {
3267 test_ukm_recorder_->ExpectEntrySourceHasUrl(
3268 kv.second.get(), embedded_test_server()->GetURL("/mock_page.html"));
3269 EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(
3270 kv.second.get(), NavigationTiming::kEarlyHintsForFirstRequestName));
3271 EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(
3272 kv.second.get(), NavigationTiming::kEarlyHintsForFinalRequestName));
3273 }
3274 }
3275
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,EarlyHints_MultipleHints)3276 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, EarlyHints_MultipleHints) {
3277 content::NavigationHandleTiming timing =
3278 NavigateWithEarlyHints(EarlyHintsPolicy::MultipleHints);
3279
3280 // There were no redirections, so the first request should be the same as the
3281 // final request.
3282 EXPECT_FALSE(timing.early_hints_for_first_request_time.is_null());
3283 EXPECT_FALSE(timing.early_hints_for_final_request_time.is_null());
3284 EXPECT_EQ(timing.early_hints_for_first_request_time,
3285 timing.early_hints_for_final_request_time);
3286
3287 // The timings of the Early Hints responses should be recorded only one time.
3288 histogram_tester_->ExpectTotalCount(
3289 internal::kHistogramEarlyHintsFirstRequestStartToEarlyHints, 1);
3290 histogram_tester_->ExpectTotalCount(
3291 internal::kHistogramEarlyHintsFinalRequestStartToEarlyHints, 1);
3292 histogram_tester_->ExpectTotalCount(
3293 internal::kHistogramEarlyHintsEarlyHintsToFinalResponseStart, 1);
3294
3295 using NavigationTiming = ukm::builders::NavigationTiming;
3296 const auto& entries =
3297 test_ukm_recorder_->GetMergedEntriesByName(NavigationTiming::kEntryName);
3298 EXPECT_EQ(1u, entries.size());
3299 for (const auto& kv : entries) {
3300 test_ukm_recorder_->ExpectEntrySourceHasUrl(
3301 kv.second.get(), embedded_test_server()->GetURL("/mock_page.html"));
3302 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3303 kv.second.get(), NavigationTiming::kEarlyHintsForFirstRequestName));
3304 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3305 kv.second.get(), NavigationTiming::kEarlyHintsForFinalRequestName));
3306 }
3307 }
3308
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,EarlyHints_HintsBeforeRedirection)3309 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
3310 EarlyHints_HintsBeforeRedirection) {
3311 content::NavigationHandleTiming timing = RedirectWithEarlyHints(
3312 EarlyHintsPolicy::MultipleHints, EarlyHintsPolicy::NoHints);
3313
3314 // The early hints were served for the first request, but not for the
3315 // redirected request.
3316 EXPECT_FALSE(timing.early_hints_for_first_request_time.is_null());
3317 EXPECT_TRUE(timing.early_hints_for_final_request_time.is_null());
3318
3319 // The timings of the Early Hints response should be recorded only for the
3320 // first request.
3321 histogram_tester_->ExpectTotalCount(
3322 internal::kHistogramEarlyHintsFirstRequestStartToEarlyHints, 1);
3323 histogram_tester_->ExpectTotalCount(
3324 internal::kHistogramEarlyHintsFinalRequestStartToEarlyHints, 0);
3325 histogram_tester_->ExpectTotalCount(
3326 internal::kHistogramEarlyHintsEarlyHintsToFinalResponseStart, 0);
3327
3328 using NavigationTiming = ukm::builders::NavigationTiming;
3329 const auto& entries =
3330 test_ukm_recorder_->GetMergedEntriesByName(NavigationTiming::kEntryName);
3331 EXPECT_EQ(1u, entries.size());
3332 for (const auto& kv : entries) {
3333 test_ukm_recorder_->ExpectEntrySourceHasUrl(
3334 kv.second.get(), embedded_test_server()->GetURL("/mock_page2.html"));
3335 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3336 kv.second.get(), NavigationTiming::kEarlyHintsForFirstRequestName));
3337 EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(
3338 kv.second.get(), NavigationTiming::kEarlyHintsForFinalRequestName));
3339 }
3340 }
3341
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,EarlyHints_HintsAfterRedirection)3342 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
3343 EarlyHints_HintsAfterRedirection) {
3344 content::NavigationHandleTiming timing = RedirectWithEarlyHints(
3345 EarlyHintsPolicy::NoHints, EarlyHintsPolicy::MultipleHints);
3346
3347 // The early hints were served for the redirected request, but not for the
3348 // first request.
3349 EXPECT_TRUE(timing.early_hints_for_first_request_time.is_null());
3350 EXPECT_FALSE(timing.early_hints_for_final_request_time.is_null());
3351
3352 // The timings of the Early Hints response should be recorded only for the
3353 // redirected request.
3354 histogram_tester_->ExpectTotalCount(
3355 internal::kHistogramEarlyHintsFirstRequestStartToEarlyHints, 0);
3356 histogram_tester_->ExpectTotalCount(
3357 internal::kHistogramEarlyHintsFinalRequestStartToEarlyHints, 1);
3358 histogram_tester_->ExpectTotalCount(
3359 internal::kHistogramEarlyHintsEarlyHintsToFinalResponseStart, 1);
3360
3361 using NavigationTiming = ukm::builders::NavigationTiming;
3362 const auto& entries =
3363 test_ukm_recorder_->GetMergedEntriesByName(NavigationTiming::kEntryName);
3364 EXPECT_EQ(1u, entries.size());
3365 for (const auto& kv : entries) {
3366 test_ukm_recorder_->ExpectEntrySourceHasUrl(
3367 kv.second.get(), embedded_test_server()->GetURL("/mock_page2.html"));
3368 EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(
3369 kv.second.get(), NavigationTiming::kEarlyHintsForFirstRequestName));
3370 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3371 kv.second.get(), NavigationTiming::kEarlyHintsForFinalRequestName));
3372 }
3373 }
3374
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,EarlyHints_HintsBeforeAndAfterRedirection)3375 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
3376 EarlyHints_HintsBeforeAndAfterRedirection) {
3377 content::NavigationHandleTiming timing = RedirectWithEarlyHints(
3378 EarlyHintsPolicy::MultipleHints, EarlyHintsPolicy::MultipleHints);
3379
3380 // The early hints were served for both the first request and the redirected
3381 // request.
3382 EXPECT_FALSE(timing.early_hints_for_first_request_time.is_null());
3383 EXPECT_FALSE(timing.early_hints_for_final_request_time.is_null());
3384 EXPECT_LT(timing.early_hints_for_first_request_time,
3385 timing.early_hints_for_final_request_time);
3386
3387 // The timings of the Early Hints response should be recorded.
3388 histogram_tester_->ExpectTotalCount(
3389 internal::kHistogramEarlyHintsFirstRequestStartToEarlyHints, 1);
3390 histogram_tester_->ExpectTotalCount(
3391 internal::kHistogramEarlyHintsFinalRequestStartToEarlyHints, 1);
3392 histogram_tester_->ExpectTotalCount(
3393 internal::kHistogramEarlyHintsEarlyHintsToFinalResponseStart, 1);
3394
3395 using NavigationTiming = ukm::builders::NavigationTiming;
3396 const auto& entries =
3397 test_ukm_recorder_->GetMergedEntriesByName(NavigationTiming::kEntryName);
3398 EXPECT_EQ(1u, entries.size());
3399 for (const auto& kv : entries) {
3400 test_ukm_recorder_->ExpectEntrySourceHasUrl(
3401 kv.second.get(), embedded_test_server()->GetURL("/mock_page2.html"));
3402 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3403 kv.second.get(), NavigationTiming::kEarlyHintsForFirstRequestName));
3404 EXPECT_TRUE(test_ukm_recorder_->EntryHasMetric(
3405 kv.second.get(), NavigationTiming::kEarlyHintsForFinalRequestName));
3406 }
3407 }
3408
3409 class NavigationPageLoadMetricsBrowserTest
3410 : public PageLoadMetricsBrowserTest,
3411 public ::testing::WithParamInterface<std::string> {
3412 public:
3413 NavigationPageLoadMetricsBrowserTest() = default;
3414 ~NavigationPageLoadMetricsBrowserTest() override = default;
3415
3416 protected:
SetUpCommandLine(base::CommandLine * command_line)3417 void SetUpCommandLine(base::CommandLine* command_line) override {
3418 scoped_feature_list_.InitAndEnableFeatureWithParameters(
3419 page_load_metrics::kPageLoadMetricsTimerDelayFeature,
3420 {
3421 // Set a very long TTL before expiration (longer than the test
3422 // timeout) so tests that are expecting deletion don't pass when
3423 // they shouldn't.
3424 {"BufferTimerDelayMillis", "100000"},
3425 });
3426 PageLoadMetricsBrowserTest::SetUpCommandLine(command_line);
3427 }
3428
3429 private:
3430 base::test::ScopedFeatureList scoped_feature_list_;
3431 };
3432
IN_PROC_BROWSER_TEST_P(NavigationPageLoadMetricsBrowserTest,FirstInputDelay)3433 IN_PROC_BROWSER_TEST_P(NavigationPageLoadMetricsBrowserTest, FirstInputDelay) {
3434 ASSERT_TRUE(embedded_test_server()->Start());
3435
3436 GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
3437 GURL url2(embedded_test_server()->GetURL(
3438 (GetParam() == "SameSite") ? "a.com" : "b.com", "/title2.html"));
3439
3440 EXPECT_THAT(histogram_tester_->GetAllSamples(
3441 internal::kHistogramFirstContentfulPaint),
3442 testing::IsEmpty());
3443
3444 // 1) Navigate to url1.
3445 EXPECT_TRUE(content::NavigateToURL(web_contents(), url1));
3446 content::RenderFrameHost* rfh_a = RenderFrameHost();
3447 content::RenderProcessHost* rfh_a_process = rfh_a->GetProcess();
3448
3449 // Simulate mouse click. FirstInputDelay won't get updated immediately.
3450 content::SimulateMouseClickAt(web_contents(), 0,
3451 blink::WebMouseEvent::Button::kLeft,
3452 gfx::Point(100, 100));
3453 // Run arbitrary script and run tasks in the brwoser to ensure the input is
3454 // processed in the renderer.
3455 EXPECT_TRUE(content::ExecJs(rfh_a, "var foo = 42;"));
3456 base::RunLoop().RunUntilIdle();
3457 content::FetchHistogramsFromChildProcesses();
3458 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstInputDelay, 0);
3459
3460 // 2) Immediately navigate to url2.
3461 if (GetParam() == "CrossSiteRendererInitiated") {
3462 EXPECT_TRUE(content::NavigateToURLFromRenderer(web_contents(), url2));
3463 } else {
3464 EXPECT_TRUE(content::NavigateToURL(web_contents(), url2));
3465 }
3466
3467 content::FetchHistogramsFromChildProcesses();
3468 if (GetParam() != "CrossSiteBrowserInitiated" ||
3469 rfh_a_process == RenderFrameHost()->GetProcess()) {
3470 // - For "SameSite" case, since the old and new RenderFrame either share a
3471 // process (with RenderDocument/back-forward cache) or the RenderFrame is
3472 // reused the metrics update will be sent to the browser during commit and
3473 // won't get ignored, successfully updating the FirstInputDelay histogram.
3474 // - For "CrossSiteRendererInitiated" case, FirstInputDelay was sent when
3475 // the renderer-initiated navigation started on the old frame.
3476 // - For "CrossSiteBrowserInitiated" case, if the old and new RenderFrame
3477 // share a process, the metrics update will be sent to the browser during
3478 // commit and won't get ignored, successfully updating the histogram.
3479 histogram_tester_->ExpectTotalCount(internal::kHistogramFirstInputDelay, 1);
3480 } else {
3481 // Note that in some cases the metrics might flakily get updated in time,
3482 // before the browser changed the current RFH. So, we can neither expect it
3483 // to be 0 all the time or 1 all the time.
3484 // TODO(crbug.com/1150242): Support updating metrics consistently on
3485 // cross-RFH cross-process navigations.
3486 }
3487 }
3488
NavigationPageLoadMetricsBrowserTestTestValues()3489 std::vector<std::string> NavigationPageLoadMetricsBrowserTestTestValues() {
3490 return {"SameSite", "CrossSiteRendererInitiated",
3491 "CrossSiteBrowserInitiated"};
3492 }
3493
3494 INSTANTIATE_TEST_SUITE_P(
3495 All,
3496 NavigationPageLoadMetricsBrowserTest,
3497 testing::ValuesIn(NavigationPageLoadMetricsBrowserTestTestValues()));
3498