Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/files/scoped_temp_dir.h" | 5 #include "base/files/scoped_temp_dir.h" |
| 6 #include "base/macros.h" | 6 #include "base/macros.h" |
| 7 #include "base/test/histogram_tester.h" | 7 #include "base/test/histogram_tester.h" |
| 8 #include "base/time/time.h" | 8 #include "base/time/time.h" |
| 9 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" | 9 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" |
| 10 #include "chrome/browser/page_load_metrics/observers/aborts_page_load_metrics_ob server.h" | 10 #include "chrome/browser/page_load_metrics/observers/aborts_page_load_metrics_ob server.h" |
| 11 #include "chrome/browser/page_load_metrics/observers/core_page_load_metrics_obse rver.h" | 11 #include "chrome/browser/page_load_metrics/observers/core_page_load_metrics_obse rver.h" |
| 12 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_me trics_observer.h" | 12 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_me trics_observer.h" |
| 13 #include "chrome/browser/page_load_metrics/observers/no_state_prefetch_page_load _metrics_observer.h" | 13 #include "chrome/browser/page_load_metrics/observers/no_state_prefetch_page_load _metrics_observer.h" |
| 14 #include "chrome/browser/page_load_metrics/page_load_tracker.h" | 14 #include "chrome/browser/page_load_metrics/page_load_tracker.h" |
| 15 #include "chrome/browser/prerender/prerender_histograms.h" | 15 #include "chrome/browser/prerender/prerender_histograms.h" |
| 16 #include "chrome/browser/prerender/prerender_origin.h" | 16 #include "chrome/browser/prerender/prerender_origin.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
| 19 #include "chrome/browser/ui/browser_navigator_params.h" | 19 #include "chrome/browser/ui/browser_navigator_params.h" |
| 20 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 20 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 21 #include "chrome/common/page_load_metrics/page_load_metrics_messages.h" | |
| 21 #include "chrome/common/pref_names.h" | 22 #include "chrome/common/pref_names.h" |
| 22 #include "chrome/common/url_constants.h" | 23 #include "chrome/common/url_constants.h" |
| 23 #include "chrome/test/base/in_process_browser_test.h" | 24 #include "chrome/test/base/in_process_browser_test.h" |
| 24 #include "chrome/test/base/ui_test_utils.h" | 25 #include "chrome/test/base/ui_test_utils.h" |
| 25 #include "components/prefs/pref_service.h" | 26 #include "components/prefs/pref_service.h" |
| 26 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 28 #include "content/public/browser/render_process_host.h" | |
| 29 #include "content/public/browser/render_view_host.h" | |
| 27 #include "content/public/test/browser_test_utils.h" | 30 #include "content/public/test/browser_test_utils.h" |
| 28 #include "content/public/test/download_test_observer.h" | 31 #include "content/public/test/download_test_observer.h" |
| 29 #include "net/http/failing_http_transaction_factory.h" | 32 #include "net/http/failing_http_transaction_factory.h" |
| 30 #include "net/http/http_cache.h" | 33 #include "net/http/http_cache.h" |
| 31 #include "net/test/embedded_test_server/embedded_test_server.h" | 34 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 32 #include "net/test/url_request/url_request_failed_job.h" | 35 #include "net/test/url_request/url_request_failed_job.h" |
| 33 #include "net/url_request/url_request_context.h" | 36 #include "net/url_request/url_request_context.h" |
| 34 #include "net/url_request/url_request_context_getter.h" | 37 #include "net/url_request/url_request_context_getter.h" |
| 35 | 38 |
| 39 namespace { | |
| 40 | |
| 41 // Waits until a PageLoadMetricsMsg_TimingUpdated message IPC is received | |
| 42 // matching a PageLoadTiming. See WaitForMatchingIPC for details. | |
| 43 class TimingUpdatedObserver : public content::BrowserMessageFilter { | |
| 44 public: | |
| 45 explicit TimingUpdatedObserver( | |
| 46 content::RenderWidgetHost* render_widget_host, | |
| 47 const page_load_metrics::PageLoadTiming& template_timing) | |
| 48 : content::BrowserMessageFilter(PageLoadMetricsMsgStart), | |
| 49 template_timing_(template_timing) { | |
| 50 DCHECK(template_timing_.dom_content_loaded_event_start || | |
|
Bryan McQuade
2017/02/16 18:18:14
could you use !template_timing_.IsEmpty() here? I
mattcary
2017/02/17 09:37:47
Thanks, IsEmpty is much better. I don't think the
| |
| 51 template_timing_.load_event_start || template_timing_.first_layout || | |
| 52 template_timing_.first_paint || template_timing_.first_text_paint || | |
| 53 template_timing_.first_image_paint || | |
| 54 template_timing_.first_contentful_paint || | |
| 55 template_timing_.first_meaningful_paint || | |
| 56 template_timing_.parse_start || template_timing_.parse_stop); | |
| 57 | |
| 58 render_widget_host->GetProcess()->AddFilter(this); | |
| 59 | |
| 60 // Roundtrip to the IO thread, to ensure that the filter is properly | |
| 61 // installed. | |
| 62 content::BrowserThread::PostTaskAndReply( | |
| 63 content::BrowserThread::IO, FROM_HERE, base::Bind(&base::DoNothing), | |
| 64 base::Bind(&TimingUpdatedObserver::Quit, this)); | |
| 65 run_loop_.reset(new base::RunLoop()); | |
| 66 run_loop_->Run(); | |
| 67 run_loop_.reset(nullptr); | |
| 68 } | |
| 69 | |
| 70 // Waits for a TimingUpdated IPC that matches the template PageLoadTiming | |
| 71 // given to the constructor. An IPC matches when its PageLoadTiming contains a | |
| 72 // non-zero field that is non-zero in the template. | |
| 73 void WaitForMatchingIPC() { | |
| 74 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 75 if (matched_timing_update_) | |
| 76 return; | |
| 77 | |
| 78 run_loop_.reset(new base::RunLoop()); | |
| 79 run_loop_->Run(); | |
|
Bryan McQuade
2017/02/16 18:18:14
can we have this time out and fail after some amou
mattcary
2017/02/17 09:37:47
The test harness will time out tests. It seems bet
| |
| 80 run_loop_.reset(nullptr); | |
| 81 } | |
| 82 | |
| 83 private: | |
| 84 bool OnMessageReceived(const IPC::Message& message) override { | |
| 85 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | |
| 86 | |
| 87 bool unused; | |
|
droger
2017/02/16 16:33:12
Do we really need this variable (since the functio
mattcary
2017/02/16 17:43:28
Probably not, but I didn't know what the conventio
mattcary
2017/02/17 09:37:47
Seems to work without the unhandled case. Hooray!
| |
| 88 IPC_BEGIN_MESSAGE_MAP(TimingUpdatedObserver, message) | |
| 89 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) | |
| 90 IPC_MESSAGE_UNHANDLED(unused = false) | |
| 91 IPC_END_MESSAGE_MAP() | |
| 92 | |
| 93 return false; | |
| 94 } | |
| 95 | |
| 96 bool OnTimingUpdated(const page_load_metrics::PageLoadTiming& timing, | |
| 97 const page_load_metrics::PageLoadMetadata& metadata) { | |
| 98 if ((template_timing_.dom_content_loaded_event_start && | |
| 99 timing.dom_content_loaded_event_start) || | |
|
droger
2017/02/16 16:33:12
Not exactly sure what would be the use case for se
mattcary
2017/02/16 17:43:28
Since I'm just checking on the single metric it's
Bryan McQuade
2017/02/16 18:18:14
yeah i think i agree that we should verify that al
mattcary
2017/02/17 09:37:47
Done.
| |
| 100 (template_timing_.load_event_start && timing.load_event_start) || | |
| 101 (template_timing_.first_layout && timing.first_layout) || | |
| 102 (template_timing_.first_paint && timing.first_paint) || | |
| 103 (template_timing_.first_text_paint && timing.first_text_paint) || | |
| 104 (template_timing_.first_image_paint && timing.first_image_paint) || | |
| 105 (template_timing_.first_contentful_paint && | |
| 106 timing.first_contentful_paint) || | |
| 107 (template_timing_.first_meaningful_paint && | |
| 108 timing.first_meaningful_paint) || | |
| 109 (template_timing_.parse_start && timing.parse_start) || | |
| 110 (template_timing_.parse_stop && timing.parse_stop)) { | |
| 111 // Ensure that any other handlers of this message, for example the real | |
| 112 // PageLoadMetric observers, get a chance to handle this message before | |
| 113 // this waiter unblocks. | |
| 114 content::BrowserThread::PostTask( | |
| 115 content::BrowserThread::IO, FROM_HERE, | |
| 116 base::Bind(&TimingUpdatedObserver::BounceTimingUpdate, this, timing, | |
| 117 metadata)); | |
| 118 } | |
| 119 return true; | |
| 120 } | |
| 121 | |
| 122 void BounceTimingUpdate(const page_load_metrics::PageLoadTiming& timing, | |
| 123 const page_load_metrics::PageLoadMetadata& metadata) { | |
| 124 content::BrowserThread::PostTask( | |
| 125 content::BrowserThread::UI, FROM_HERE, | |
| 126 base::Bind(&TimingUpdatedObserver::SetTimingUpdatedAndQuit, this)); | |
| 127 } | |
| 128 | |
| 129 void Quit() { | |
| 130 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 131 if (run_loop_) | |
| 132 run_loop_->Quit(); | |
| 133 } | |
| 134 | |
| 135 void SetTimingUpdatedAndQuit() { | |
| 136 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 137 matched_timing_update_ = true; | |
| 138 Quit(); | |
| 139 } | |
| 140 | |
| 141 ~TimingUpdatedObserver() override {} | |
| 142 | |
| 143 std::unique_ptr<base::RunLoop> run_loop_; | |
| 144 page_load_metrics::PageLoadTiming template_timing_; | |
| 145 bool matched_timing_update_ = false; | |
| 146 }; | |
| 147 | |
| 148 } // namespace | |
| 149 | |
| 36 class PageLoadMetricsBrowserTest : public InProcessBrowserTest { | 150 class PageLoadMetricsBrowserTest : public InProcessBrowserTest { |
| 37 public: | 151 public: |
| 38 PageLoadMetricsBrowserTest() {} | 152 PageLoadMetricsBrowserTest() {} |
| 39 ~PageLoadMetricsBrowserTest() override {} | 153 ~PageLoadMetricsBrowserTest() override {} |
| 40 | 154 |
| 41 protected: | 155 protected: |
| 42 void NavigateToUntrackedUrl() { | 156 void NavigateToUntrackedUrl() { |
| 43 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); | 157 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); |
| 44 } | 158 } |
| 45 | 159 |
| 46 bool NoPageLoadMetricsRecorded() { | 160 bool NoPageLoadMetricsRecorded() { |
| 47 return histogram_tester_.GetTotalCountsForPrefix("PageLoad.").empty(); | 161 return histogram_tester_.GetTotalCountsForPrefix("PageLoad.").empty(); |
| 48 } | 162 } |
| 49 | 163 |
| 164 scoped_refptr<TimingUpdatedObserver> CreateFCPTimingUpdatedObserver() { | |
| 165 content::WebContents* web_contents = | |
| 166 browser()->tab_strip_model()->GetActiveWebContents(); | |
| 167 page_load_metrics::PageLoadTiming template_timing; | |
| 168 template_timing.first_contentful_paint = | |
|
Bryan McQuade
2017/02/16 18:18:14
maybe add a comment noting that the actual value i
mattcary
2017/02/17 09:37:47
Done.
| |
| 169 base::TimeDelta::FromInternalValue(1); | |
| 170 scoped_refptr<TimingUpdatedObserver> observer(new TimingUpdatedObserver( | |
| 171 web_contents->GetRenderViewHost()->GetWidget(), template_timing)); | |
| 172 return observer; | |
| 173 } | |
| 174 | |
| 50 base::HistogramTester histogram_tester_; | 175 base::HistogramTester histogram_tester_; |
| 51 | 176 |
| 52 private: | 177 private: |
| 53 DISALLOW_COPY_AND_ASSIGN(PageLoadMetricsBrowserTest); | 178 DISALLOW_COPY_AND_ASSIGN(PageLoadMetricsBrowserTest); |
| 54 }; | 179 }; |
| 55 | 180 |
| 56 void FailAllNetworkTransactions(net::URLRequestContextGetter* getter) { | 181 void FailAllNetworkTransactions(net::URLRequestContextGetter* getter) { |
| 57 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 182 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 58 net::HttpCache* cache( | 183 net::HttpCache* cache( |
| 59 getter->GetURLRequestContext()->http_transaction_factory()->GetCache()); | 184 getter->GetURLRequestContext()->http_transaction_factory()->GetCache()); |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 | 633 |
| 509 histogram_tester_.ExpectUniqueSample( | 634 histogram_tester_.ExpectUniqueSample( |
| 510 internal::kHistogramFirstMeaningfulPaintStatus, | 635 internal::kHistogramFirstMeaningfulPaintStatus, |
| 511 internal::FIRST_MEANINGFUL_PAINT_DID_NOT_REACH_NETWORK_STABLE, 1); | 636 internal::FIRST_MEANINGFUL_PAINT_DID_NOT_REACH_NETWORK_STABLE, 1); |
| 512 histogram_tester_.ExpectTotalCount( | 637 histogram_tester_.ExpectTotalCount( |
| 513 internal::kHistogramFirstMeaningfulPaint, 0); | 638 internal::kHistogramFirstMeaningfulPaint, 0); |
| 514 histogram_tester_.ExpectTotalCount( | 639 histogram_tester_.ExpectTotalCount( |
| 515 internal::kHistogramParseStartToFirstMeaningfulPaint, 0); | 640 internal::kHistogramParseStartToFirstMeaningfulPaint, 0); |
| 516 } | 641 } |
| 517 | 642 |
| 518 // Flaky on Linux (timing out or failing in an expectation) crbug.com/657022 | |
| 519 #if defined(OS_LINUX) | |
| 520 #define MAYBE_NoStatePrefetchObserverCacheable \ | |
| 521 DISABLED_NoStatePrefetchObserverCacheable | |
| 522 #else | |
| 523 #define MAYBE_NoStatePrefetchObserverCacheable NoStatePrefetchObserverCacheable | |
| 524 #endif | |
| 525 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, | 643 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, |
| 526 MAYBE_NoStatePrefetchObserverCacheable) { | 644 NoStatePrefetchObserverCacheable) { |
| 527 ASSERT_TRUE(embedded_test_server()->Start()); | 645 ASSERT_TRUE(embedded_test_server()->Start()); |
| 528 | 646 |
| 647 scoped_refptr<TimingUpdatedObserver> fcp_observer = | |
| 648 CreateFCPTimingUpdatedObserver(); | |
| 649 | |
| 529 ui_test_utils::NavigateToURL(browser(), | 650 ui_test_utils::NavigateToURL(browser(), |
| 530 embedded_test_server()->GetURL("/title1.html")); | 651 embedded_test_server()->GetURL("/title1.html")); |
| 531 NavigateToUntrackedUrl(); | 652 |
| 653 fcp_observer->WaitForMatchingIPC(); | |
| 532 | 654 |
| 533 histogram_tester_.ExpectTotalCount( | 655 histogram_tester_.ExpectTotalCount( |
| 534 "Prerender.none_PrefetchTTFCP.Reference.NoStore.Visible", 0); | 656 "Prerender.none_PrefetchTTFCP.Reference.NoStore.Visible", 0); |
| 535 histogram_tester_.ExpectTotalCount( | 657 histogram_tester_.ExpectTotalCount( |
| 536 "Prerender.none_PrefetchTTFCP.Reference.Cacheable.Visible", 1); | 658 "Prerender.none_PrefetchTTFCP.Reference.Cacheable.Visible", 1); |
| 537 } | 659 } |
| 538 | 660 |
| 539 // Flaky on Linux (timing out or failing in an expectation) crbug.com/657022 | |
| 540 #if defined(OS_LINUX) | |
| 541 #define MAYBE_NoStatePrefetchObserverNoStore \ | |
| 542 DISABLED_NoStatePrefetchObserverNoStore | |
| 543 #else | |
| 544 #define MAYBE_NoStatePrefetchObserverNoStore NoStatePrefetchObserverNoStore | |
| 545 #endif | |
| 546 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, | 661 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, |
| 547 MAYBE_NoStatePrefetchObserverNoStore) { | 662 NoStatePrefetchObserverNoStore) { |
| 548 ASSERT_TRUE(embedded_test_server()->Start()); | 663 ASSERT_TRUE(embedded_test_server()->Start()); |
| 549 | 664 |
| 665 scoped_refptr<TimingUpdatedObserver> fcp_observer = | |
| 666 CreateFCPTimingUpdatedObserver(); | |
| 667 | |
| 550 ui_test_utils::NavigateToURL(browser(), | 668 ui_test_utils::NavigateToURL(browser(), |
| 551 embedded_test_server()->GetURL("/nostore.html")); | 669 embedded_test_server()->GetURL("/nostore.html")); |
| 552 NavigateToUntrackedUrl(); | 670 |
| 671 fcp_observer->WaitForMatchingIPC(); | |
| 553 | 672 |
| 554 histogram_tester_.ExpectTotalCount( | 673 histogram_tester_.ExpectTotalCount( |
| 555 "Prerender.none_PrefetchTTFCP.Reference.NoStore.Visible", 1); | 674 "Prerender.none_PrefetchTTFCP.Reference.NoStore.Visible", 1); |
| 556 histogram_tester_.ExpectTotalCount( | 675 histogram_tester_.ExpectTotalCount( |
| 557 "Prerender.none_PrefetchTTFCP.Reference.Cacheable.Visible", 0); | 676 "Prerender.none_PrefetchTTFCP.Reference.Cacheable.Visible", 0); |
| 558 } | 677 } |
| 559 | 678 |
| 560 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, CSSTiming) { | 679 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, CSSTiming) { |
| 561 ASSERT_TRUE(embedded_test_server()->Start()); | 680 ASSERT_TRUE(embedded_test_server()->Start()); |
| 562 | 681 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 584 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL( | 703 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL( |
| 585 "/page_load_metrics/large.html")); | 704 "/page_load_metrics/large.html")); |
| 586 NavigateToUntrackedUrl(); | 705 NavigateToUntrackedUrl(); |
| 587 | 706 |
| 588 histogram_tester_.ExpectTotalCount(internal::kHistogramTotalBytes, 1); | 707 histogram_tester_.ExpectTotalCount(internal::kHistogramTotalBytes, 1); |
| 589 | 708 |
| 590 // Verify that there is a single sample recorded in the 10kB bucket (the size | 709 // Verify that there is a single sample recorded in the 10kB bucket (the size |
| 591 // of the main HTML response). | 710 // of the main HTML response). |
| 592 histogram_tester_.ExpectBucketCount(internal::kHistogramTotalBytes, 10, 1); | 711 histogram_tester_.ExpectBucketCount(internal::kHistogramTotalBytes, 10, 1); |
| 593 } | 712 } |
| OLD | NEW |