| // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/macros.h" |
| #include "base/test/histogram_tester.h" |
| #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" |
| #include "chrome/browser/page_load_metrics/observers/aborts_page_load_metrics_observer.h" |
| #include "chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h" |
| #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_navigator_params.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| |
| class MetricsWebContentsObserverBrowserTest : public InProcessBrowserTest { |
| public: |
| MetricsWebContentsObserverBrowserTest() {} |
| ~MetricsWebContentsObserverBrowserTest() override {} |
| |
| protected: |
| void NavigateToUntrackedUrl() { |
| ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); |
| } |
| |
| base::HistogramTester histogram_tester_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserverBrowserTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, NoNavigation) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| histogram_tester_.ExpectTotalCount(internal::kHistogramCommit, 0); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramDomContentLoaded, 0); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramLoad, 0); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, NewPage) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/title1.html")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount(internal::kHistogramDomContentLoaded, 1); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramLoad, 1); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 1); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramParseDuration, 1); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramParseBlockedOnScriptLoad, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| SamePageNavigation) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/title1.html")); |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL("/title1.html#hash")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount(internal::kHistogramDomContentLoaded, 1); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramLoad, 1); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| SameUrlNavigation) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/title1.html")); |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/title1.html")); |
| NavigateToUntrackedUrl(); |
| |
| // We expect one histogram sample for each navigation to title1.html. |
| histogram_tester_.ExpectTotalCount(internal::kHistogramCommit, 2); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramDomContentLoaded, 2); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramLoad, 2); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 2); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| NonHtmlMainResource) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/circle.svg")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount(internal::kHistogramCommit, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| NonHttpOrHttpsUrl) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount(internal::kHistogramCommit, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| PreloadDocumentWrite) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_external_script.html")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| NoPreloadDocumentWrite) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_no_script.html")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, NoDocumentWrite) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/title1.html")); |
| NavigateToUntrackedUrl(); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| DocumentWriteBlock) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_script_block.html")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| DocumentWriteReload) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_script_block.html")); |
| |
| // Reload should not log the histogram as the script is not blocked. |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_script_block.html")); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_script_block.html")); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
| |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockReloadCount, 2); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| DocumentWriteAsync) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_script_async.html")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| DocumentWriteSameDomain) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_external_script.html")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| NoDocumentWriteScript) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL( |
| "/page_load_metrics/document_write_no_script.html")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, BadXhtml) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| // When an XHTML page contains invalid XML, it causes a paint of the error |
| // message without a layout. Page load metrics currently treats this as an |
| // error. Eventually, we'll fix this by special casing the handling of |
| // documents with non-well-formed XML on the blink side. See crbug.com/627607 |
| // for more. |
| ui_test_utils::NavigateToURL( |
| browser(), |
| embedded_test_server()->GetURL("/page_load_metrics/badxml.xhtml")); |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 0); |
| histogram_tester_.ExpectTotalCount(internal::kHistogramFirstPaint, 0); |
| histogram_tester_.ExpectBucketCount(page_load_metrics::internal::kErrorEvents, |
| page_load_metrics::ERR_BAD_TIMING_IPC, 1); |
| } |
| |
| // Test code that aborts provisional navigations. |
| // TODO(csharrison): Move these to unit tests once the navigation API in content |
| // properly calls NavigationHandle/NavigationThrottle methods. |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| AbortNewNavigation) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| GURL url(embedded_test_server()->GetURL("/title1.html")); |
| chrome::NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK); |
| content::TestNavigationManager manager( |
| browser()->tab_strip_model()->GetActiveWebContents(), url); |
| |
| chrome::Navigate(¶ms); |
| EXPECT_TRUE(manager.WaitForWillStartRequest()); |
| |
| GURL url2(embedded_test_server()->GetURL("/title2.html")); |
| chrome::NavigateParams params2(browser(), url2, |
| ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); |
| content::TestNavigationManager manager2( |
| browser()->tab_strip_model()->GetActiveWebContents(), url2); |
| chrome::Navigate(¶ms2); |
| |
| manager2.WaitForNavigationFinished(); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramAbortNewNavigationBeforeCommit, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, AbortReload) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| GURL url(embedded_test_server()->GetURL("/title1.html")); |
| chrome::NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK); |
| content::TestNavigationManager manager( |
| browser()->tab_strip_model()->GetActiveWebContents(), url); |
| |
| chrome::Navigate(¶ms); |
| EXPECT_TRUE(manager.WaitForWillStartRequest()); |
| |
| chrome::NavigateParams params2(browser(), url, ui::PAGE_TRANSITION_RELOAD); |
| content::TestNavigationManager manager2( |
| browser()->tab_strip_model()->GetActiveWebContents(), url); |
| chrome::Navigate(¶ms2); |
| |
| manager2.WaitForNavigationFinished(); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramAbortReloadBeforeCommit, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, AbortClose) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| GURL url(embedded_test_server()->GetURL("/title1.html")); |
| chrome::NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK); |
| content::TestNavigationManager manager( |
| browser()->tab_strip_model()->GetActiveWebContents(), url); |
| |
| chrome::Navigate(¶ms); |
| EXPECT_TRUE(manager.WaitForWillStartRequest()); |
| |
| browser()->tab_strip_model()->GetActiveWebContents()->Close(); |
| |
| manager.WaitForNavigationFinished(); |
| |
| histogram_tester_.ExpectTotalCount(internal::kHistogramAbortCloseBeforeCommit, |
| 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, AbortMultiple) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| GURL url(embedded_test_server()->GetURL("/title1.html")); |
| chrome::NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK); |
| content::TestNavigationManager manager( |
| browser()->tab_strip_model()->GetActiveWebContents(), url); |
| |
| chrome::Navigate(¶ms); |
| EXPECT_TRUE(manager.WaitForWillStartRequest()); |
| |
| GURL url2(embedded_test_server()->GetURL("/title2.html")); |
| chrome::NavigateParams params2(browser(), url2, ui::PAGE_TRANSITION_TYPED); |
| content::TestNavigationManager manager2( |
| browser()->tab_strip_model()->GetActiveWebContents(), url2); |
| chrome::Navigate(¶ms2); |
| |
| EXPECT_TRUE(manager2.WaitForWillStartRequest()); |
| manager.WaitForNavigationFinished(); |
| |
| GURL url3(embedded_test_server()->GetURL("/title3.html")); |
| chrome::NavigateParams params3(browser(), url3, ui::PAGE_TRANSITION_TYPED); |
| content::TestNavigationManager manager3( |
| browser()->tab_strip_model()->GetActiveWebContents(), url3); |
| chrome::Navigate(¶ms3); |
| |
| EXPECT_TRUE(manager3.WaitForWillStartRequest()); |
| manager2.WaitForNavigationFinished(); |
| |
| manager3.WaitForNavigationFinished(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramAbortNewNavigationBeforeCommit, 2); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| AbortClientRedirect) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| GURL first_url(embedded_test_server()->GetURL("/title1.html")); |
| ui_test_utils::NavigateToURL(browser(), first_url); |
| |
| GURL second_url(embedded_test_server()->GetURL("/title2.html")); |
| chrome::NavigateParams params(browser(), second_url, |
| ui::PAGE_TRANSITION_LINK); |
| content::TestNavigationManager manager( |
| browser()->tab_strip_model()->GetActiveWebContents(), second_url); |
| chrome::Navigate(¶ms); |
| EXPECT_TRUE(manager.WaitForWillStartRequest()); |
| |
| { |
| content::TestNavigationManager reload_manager( |
| browser()->tab_strip_model()->GetActiveWebContents(), first_url); |
| EXPECT_TRUE(content::ExecuteScript( |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| "window.location.reload();")); |
| } |
| |
| manager.WaitForNavigationFinished(); |
| |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramAbortClientRedirectBeforeCommit, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| FirstMeaningfulPaintRecorded) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/title1.html")); |
| |
| // Wait until the renderer finishes observing layouts. |
| const int kNetworkIdleTime = 2000; |
| const int kMargin = 500; |
| const std::string javascript = base::StringPrintf( |
| "setTimeout(() => window.domAutomationController.send(true), %d)", |
| kNetworkIdleTime + kMargin); |
| bool result; |
| EXPECT_TRUE(content::ExecuteScriptAndExtractBool( |
| browser()->tab_strip_model()->GetActiveWebContents(), |
| javascript, &result)); |
| EXPECT_TRUE(result); |
| |
| NavigateToUntrackedUrl(); |
| histogram_tester_.ExpectUniqueSample( |
| internal::kHistogramFirstMeaningfulPaintStatus, |
| internal::FIRST_MEANINGFUL_PAINT_RECORDED, 1); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramFirstMeaningfulPaint, 1); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramParseStartToFirstMeaningfulPaint, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, |
| FirstMeaningfulPaintNotRecorded) { |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| |
| ui_test_utils::NavigateToURL(browser(), |
| embedded_test_server()->GetURL("/title1.html")); |
| |
| // Navigate away before a FMP is reported. |
| NavigateToUntrackedUrl(); |
| |
| histogram_tester_.ExpectUniqueSample( |
| internal::kHistogramFirstMeaningfulPaintStatus, |
| internal::FIRST_MEANINGFUL_PAINT_DID_NOT_REACH_NETWORK_STABLE, 1); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramFirstMeaningfulPaint, 0); |
| histogram_tester_.ExpectTotalCount( |
| internal::kHistogramParseStartToFirstMeaningfulPaint, 0); |
| } |