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(&params);
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(&params);
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(&params2);
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(&params);
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(&params2);
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(&params);
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(&params);
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(&params2);
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(&params3);
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(&params);
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