Index: chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc |
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc |
index 2e54df31d741d14370389f4d6555a932de1fbe4d..8d69c71e8ddf51c0cebb4c566fda09100271e219 100644 |
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc |
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc |
@@ -38,9 +38,9 @@ |
namespace { |
-// Waits until specified timing and metadata expectations are satisfied. |
-class PageLoadMetricsWaiter |
- : public page_load_metrics::MetricsWebContentsObserver::TestingObserver { |
+// Waits until a PageLoadMetricsMsg_TimingUpdated message IPC is received |
+// matching a PageLoadTiming. See WaitForMatchingIPC for details. |
+class TimingUpdatedObserver : public content::BrowserMessageFilter { |
public: |
// A bitvector to express which timing fields to match on. |
enum ExpectedTimingFields { |
@@ -49,40 +49,57 @@ |
STYLE_UPDATE_BEFORE_FCP = 1 << 2 |
}; |
- explicit PageLoadMetricsWaiter(content::WebContents* web_contents) |
- : TestingObserver(web_contents) {} |
- |
- ~PageLoadMetricsWaiter() override { DCHECK_EQ(nullptr, run_loop_.get()); } |
- |
- // Add the given expectation to match on. |
- void AddExpectation(ExpectedTimingFields fields) { |
- matching_fields_ |= fields; |
- } |
- |
- // Instructs observer to also watch for |count| |
- // WebLoadingBehaviorDocumentWriteBlockReload events. |
- void ExpectDocumentWriteBlockReload(int count) { |
- match_document_write_block_reload_ = count; |
- } |
- |
- // Waits for a TimingUpdated IPC that matches the fields set by |
- // |AddExpectation|. All matching fields must be set in a TimingUpdated |
- // IPC for it to end this wait. |
- void Wait() { |
- if (expectations_satisfied_) |
- return; |
- |
+ explicit TimingUpdatedObserver(content::RenderWidgetHost* render_widget_host) |
+ : content::BrowserMessageFilter(PageLoadMetricsMsgStart) { |
+ render_widget_host->GetProcess()->AddFilter(this); |
+ |
+ // Roundtrip to the IO thread, to ensure that the filter is properly |
+ // installed. |
+ content::BrowserThread::PostTaskAndReply( |
+ content::BrowserThread::IO, FROM_HERE, base::BindOnce(&base::DoNothing), |
+ base::BindOnce(&TimingUpdatedObserver::Quit, this)); |
run_loop_.reset(new base::RunLoop()); |
run_loop_->Run(); |
run_loop_.reset(nullptr); |
- |
- EXPECT_TRUE(expectations_satisfied_); |
+ } |
+ |
+ // Add the given timing fields to the set of fields to match on. |
+ void AddMatchingFields(ExpectedTimingFields fields) { |
+ matching_fields_ |= fields; |
+ } |
+ |
+ // Instructs observer to also watch for |count| |
+ // WebLoadingBehaviorDocumentWriteBlockReload events. |
+ void MatchDocumentWriteBlockReload(int count) { |
+ match_document_write_block_reload_ = count; |
+ } |
+ |
+ // Waits for a TimingUpdated IPC that matches the fields set by |
+ // |AddMatchingFields|. All matching fields must be set in a TimingUpdated |
+ // IPC for it to end this wait. |
+ void WaitForMatchingIPC() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ if (matched_timing_update_) |
+ return; |
+ |
+ run_loop_.reset(new base::RunLoop()); |
+ run_loop_->Run(); |
+ run_loop_.reset(nullptr); |
} |
private: |
- void OnTimingUpdated( |
- const page_load_metrics::PageLoadTiming& timing, |
- const page_load_metrics::PageLoadMetadata& metadata) override { |
+ bool OnMessageReceived(const IPC::Message& message) override { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
+ |
+ IPC_BEGIN_MESSAGE_MAP(TimingUpdatedObserver, message) |
+ IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) |
+ IPC_END_MESSAGE_MAP() |
+ |
+ return false; |
+ } |
+ |
+ bool OnTimingUpdated(const page_load_metrics::PageLoadTiming& timing, |
+ const page_load_metrics::PageLoadMetadata& metadata) { |
if (match_document_write_block_reload_ > 0 && |
metadata.behavior_flags & |
blink::WebLoadingBehaviorFlag:: |
@@ -91,7 +108,7 @@ |
} |
if (match_document_write_block_reload_ > 0) { |
- return; |
+ return true; |
} |
if ((!(matching_fields_ & FIRST_PAINT) || |
@@ -100,15 +117,41 @@ |
timing.paint_timing.first_contentful_paint) && |
(!(matching_fields_ & STYLE_UPDATE_BEFORE_FCP) || |
timing.style_sheet_timing.update_style_duration_before_fcp)) { |
- expectations_satisfied_ = true; |
- if (run_loop_) |
- run_loop_->Quit(); |
+ // Ensure that any other handlers of this message, for example the real |
+ // PageLoadMetric observers, get a chance to handle this message before |
+ // this waiter unblocks. |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
+ base::BindOnce(&TimingUpdatedObserver::BounceTimingUpdate, this, |
+ timing, metadata)); |
} |
- } |
+ return true; |
+ } |
+ |
+ void BounceTimingUpdate(const page_load_metrics::PageLoadTiming& timing, |
+ const page_load_metrics::PageLoadMetadata& metadata) { |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, FROM_HERE, |
+ base::BindOnce(&TimingUpdatedObserver::SetTimingUpdatedAndQuit, this)); |
+ } |
+ |
+ void Quit() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ if (run_loop_) |
+ run_loop_->Quit(); |
+ } |
+ |
+ void SetTimingUpdatedAndQuit() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ matched_timing_update_ = true; |
+ Quit(); |
+ } |
+ |
+ ~TimingUpdatedObserver() override {} |
std::unique_ptr<base::RunLoop> run_loop_; |
int matching_fields_ = 0; // A bitvector composed from ExpectedTimingFields. |
- bool expectations_satisfied_ = false; |
+ bool matched_timing_update_ = false; |
int match_document_write_block_reload_ = 0; |
}; |
@@ -135,10 +178,12 @@ |
return total_pageload_histograms - total_internal_histograms == 0; |
} |
- std::unique_ptr<PageLoadMetricsWaiter> CreatePageLoadMetricsWaiter() { |
+ scoped_refptr<TimingUpdatedObserver> CreateTimingUpdatedObserver() { |
content::WebContents* web_contents = |
browser()->tab_strip_model()->GetActiveWebContents(); |
- return base::MakeUnique<PageLoadMetricsWaiter>(web_contents); |
+ scoped_refptr<TimingUpdatedObserver> observer(new TimingUpdatedObserver( |
+ web_contents->GetRenderViewHost()->GetWidget())); |
+ return observer; |
} |
base::HistogramTester histogram_tester_; |
@@ -294,14 +339,15 @@ |
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PreloadDocumentWrite) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_CONTENTFUL_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::FIRST_CONTENTFUL_PAINT); |
ui_test_utils::NavigateToURL( |
browser(), embedded_test_server()->GetURL( |
"/page_load_metrics/document_write_external_script.html")); |
- fcp_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount( |
internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 1); |
@@ -322,13 +368,14 @@ |
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoDocumentWrite) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_CONTENTFUL_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::FIRST_CONTENTFUL_PAINT); |
ui_test_utils::NavigateToURL(browser(), |
embedded_test_server()->GetURL("/title1.html")); |
- fcp_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount( |
internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0); |
@@ -340,14 +387,15 @@ |
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, DocumentWriteBlock) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_CONTENTFUL_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::FIRST_CONTENTFUL_PAINT); |
ui_test_utils::NavigateToURL( |
browser(), embedded_test_server()->GetURL( |
"/page_load_metrics/document_write_script_block.html")); |
- fcp_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount( |
internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
@@ -357,12 +405,13 @@ |
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, DocumentWriteReload) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_CONTENTFUL_PAINT); |
- std::unique_ptr<PageLoadMetricsWaiter> reload_waiter = |
- CreatePageLoadMetricsWaiter(); |
- reload_waiter->ExpectDocumentWriteBlockReload(2); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::FIRST_CONTENTFUL_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> reload_observer = |
+ CreateTimingUpdatedObserver(); |
+ reload_observer->MatchDocumentWriteBlockReload(2); |
ui_test_utils::NavigateToURL( |
browser(), embedded_test_server()->GetURL( |
@@ -380,8 +429,8 @@ |
histogram_tester_.ExpectTotalCount( |
internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
- fcp_waiter->Wait(); |
- reload_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
+ reload_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount( |
internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1); |
@@ -439,9 +488,9 @@ |
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, MAYBE_BadXhtml) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> timing_waiter = |
- CreatePageLoadMetricsWaiter(); |
- timing_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> timing_observer = |
+ CreateTimingUpdatedObserver(); |
+ timing_observer->AddMatchingFields(TimingUpdatedObserver::FIRST_PAINT); |
// 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 |
@@ -452,7 +501,7 @@ |
browser(), |
embedded_test_server()->GetURL("/page_load_metrics/badxml.xhtml")); |
- timing_waiter->Wait(); |
+ timing_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 0); |
histogram_tester_.ExpectTotalCount(internal::kHistogramFirstPaint, 0); |
@@ -639,14 +688,15 @@ |
FirstMeaningfulPaintNotRecorded) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_CONTENTFUL_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::FIRST_CONTENTFUL_PAINT); |
ui_test_utils::NavigateToURL( |
browser(), embedded_test_server()->GetURL( |
"/page_load_metrics/page_with_active_connections.html")); |
- fcp_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
// Navigate away before a FMP is reported. |
NavigateToUntrackedUrl(); |
@@ -664,14 +714,15 @@ |
NoStatePrefetchObserverCacheable) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_CONTENTFUL_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::FIRST_CONTENTFUL_PAINT); |
ui_test_utils::NavigateToURL(browser(), |
embedded_test_server()->GetURL("/title1.html")); |
- fcp_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount( |
"Prerender.none_PrefetchTTFCP.Reference.NoStore.Visible", 0); |
@@ -683,14 +734,15 @@ |
NoStatePrefetchObserverNoStore) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::FIRST_CONTENTFUL_PAINT); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::FIRST_CONTENTFUL_PAINT); |
ui_test_utils::NavigateToURL(browser(), |
embedded_test_server()->GetURL("/nostore.html")); |
- fcp_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount( |
"Prerender.none_PrefetchTTFCP.Reference.NoStore.Visible", 1); |
@@ -701,9 +753,10 @@ |
IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, CSSTiming) { |
ASSERT_TRUE(embedded_test_server()->Start()); |
- std::unique_ptr<PageLoadMetricsWaiter> fcp_waiter = |
- CreatePageLoadMetricsWaiter(); |
- fcp_waiter->AddExpectation(PageLoadMetricsWaiter::STYLE_UPDATE_BEFORE_FCP); |
+ scoped_refptr<TimingUpdatedObserver> fcp_observer = |
+ CreateTimingUpdatedObserver(); |
+ fcp_observer->AddMatchingFields( |
+ TimingUpdatedObserver::STYLE_UPDATE_BEFORE_FCP); |
// Careful: Blink code clamps timestamps to 5us, so any CSS parsing we do here |
// must take >> 5us, otherwise we'll log 0 for the value and it will remain |
@@ -712,7 +765,7 @@ |
browser(), |
embedded_test_server()->GetURL("/page_load_metrics/page_with_css.html")); |
NavigateToUntrackedUrl(); |
- fcp_waiter->Wait(); |
+ fcp_observer->WaitForMatchingIPC(); |
histogram_tester_.ExpectTotalCount(internal::kHistogramFirstContentfulPaint, |
1); |