1 // Copyright 2016 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 "chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.h"
6 
7 #include <memory>
8 
9 #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
10 #include "components/page_load_metrics/browser/page_load_tracker.h"
11 #include "components/page_load_metrics/browser/protocol_util.h"
12 #include "components/page_load_metrics/common/test/page_load_metrics_test_util.h"
13 
14 class ProtocolPageLoadMetricsObserverTest
15     : public page_load_metrics::PageLoadMetricsObserverTestHarness {
16  protected:
RegisterObservers(page_load_metrics::PageLoadTracker * tracker)17   void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
18     std::unique_ptr<ProtocolPageLoadMetricsObserver> observer =
19         std::make_unique<ProtocolPageLoadMetricsObserver>();
20     observer_ = observer.get();
21     tracker->AddObserver(std::move(observer));
22   }
23 
InitializeTestPageLoadTiming(page_load_metrics::mojom::PageLoadTiming * timing)24   void InitializeTestPageLoadTiming(
25       page_load_metrics::mojom::PageLoadTiming* timing) {
26     page_load_metrics::InitPageLoadTimingForTest(timing);
27     timing->navigation_start = base::Time::FromDoubleT(1);
28     timing->parse_timing->parse_start = base::TimeDelta::FromMilliseconds(100);
29     timing->paint_timing->first_paint = base::TimeDelta::FromMilliseconds(200);
30     timing->paint_timing->first_contentful_paint =
31         base::TimeDelta::FromMilliseconds(300);
32     timing->paint_timing->first_meaningful_paint =
33         base::TimeDelta::FromMilliseconds(400);
34     timing->document_timing->dom_content_loaded_event_start =
35         base::TimeDelta::FromMilliseconds(600);
36     timing->document_timing->load_event_start =
37         base::TimeDelta::FromMilliseconds(1000);
38     PopulateRequiredTimingFields(timing);
39   }
40 
SimulateNavigation(net::HttpResponseInfo::ConnectionInfo connection_info)41   void SimulateNavigation(
42       net::HttpResponseInfo::ConnectionInfo connection_info) {
43     NavigateAndCommit(GURL("http://google.com"));
44 
45     // Force the ConnectionInfo that the observer received from the
46     // NavigationHandle.
47     observer_->protocol_ =
48         page_load_metrics::GetNetworkProtocol(connection_info);
49 
50     page_load_metrics::mojom::PageLoadTiming timing;
51     InitializeTestPageLoadTiming(&timing);
52     tester()->SimulateTimingUpdate(timing);
53 
54     // Navigate again to force OnComplete, which happens when a new navigation
55     // occurs.
56     NavigateAndCommit(GURL("http://example.com"));
57   }
58 
CountTotalProtocolMetricsRecorded()59   int CountTotalProtocolMetricsRecorded() {
60     int count = 0;
61 
62     base::HistogramTester::CountsMap counts_map =
63         tester()->histogram_tester().GetTotalCountsForPrefix(
64             "PageLoad.Clients.Protocol.");
65     for (const auto& entry : counts_map)
66       count += entry.second;
67     return count;
68   }
69 
CheckHistograms(int expected_count,const std::string & protocol)70   void CheckHistograms(int expected_count, const std::string& protocol) {
71     EXPECT_EQ(expected_count, CountTotalProtocolMetricsRecorded());
72     if (expected_count == 0)
73       return;
74 
75     std::string prefix = "PageLoad.Clients.Protocol.";
76     prefix += protocol;
77 
78     tester()->histogram_tester().ExpectTotalCount(
79         prefix + ".ParseTiming.NavigationToParseStart", 1);
80     tester()->histogram_tester().ExpectTotalCount(
81         prefix + ".PaintTiming.ParseStartToFirstContentfulPaint", 1);
82     tester()->histogram_tester().ExpectTotalCount(
83         prefix + ".PaintTiming.NavigationToFirstContentfulPaint", 1);
84     tester()->histogram_tester().ExpectTotalCount(
85         prefix + ".Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint",
86         1);
87     tester()->histogram_tester().ExpectTotalCount(
88         prefix + ".Experimental.PaintTiming.NavigationToFirstMeaningfulPaint",
89         1);
90     tester()->histogram_tester().ExpectTotalCount(
91         prefix + ".DocumentTiming.NavigationToDOMContentLoadedEventFired", 1);
92     tester()->histogram_tester().ExpectTotalCount(
93         prefix + ".DocumentTiming.NavigationToLoadEventFired", 1);
94   }
95 
96   ProtocolPageLoadMetricsObserver* observer_;
97 };
98 
TEST_F(ProtocolPageLoadMetricsObserverTest,H11Navigation)99 TEST_F(ProtocolPageLoadMetricsObserverTest, H11Navigation) {
100   SimulateNavigation(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1);
101   CheckHistograms(7, "H11");
102 }
103 
TEST_F(ProtocolPageLoadMetricsObserverTest,H10Navigation)104 TEST_F(ProtocolPageLoadMetricsObserverTest, H10Navigation) {
105   SimulateNavigation(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_0);
106   CheckHistograms(0, "");
107 }
108 
TEST_F(ProtocolPageLoadMetricsObserverTest,H09Navigation)109 TEST_F(ProtocolPageLoadMetricsObserverTest, H09Navigation) {
110   SimulateNavigation(net::HttpResponseInfo::CONNECTION_INFO_HTTP0_9);
111   CheckHistograms(0, "");
112 }
113 
TEST_F(ProtocolPageLoadMetricsObserverTest,H2Navigation)114 TEST_F(ProtocolPageLoadMetricsObserverTest, H2Navigation) {
115   SimulateNavigation(net::HttpResponseInfo::CONNECTION_INFO_HTTP2);
116   CheckHistograms(7, "H2");
117 }
118 
TEST_F(ProtocolPageLoadMetricsObserverTest,QuicNavigation)119 TEST_F(ProtocolPageLoadMetricsObserverTest, QuicNavigation) {
120   SimulateNavigation(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
121   CheckHistograms(7, "QUIC");
122 }
123 
TEST_F(ProtocolPageLoadMetricsObserverTest,UnknownNavigation)124 TEST_F(ProtocolPageLoadMetricsObserverTest, UnknownNavigation) {
125   SimulateNavigation(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN);
126   CheckHistograms(0, "");
127 }
128