1 // Copyright 2017 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 "components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h"
6 
7 #include <memory>
8 #include <vector>
9 
10 #include "base/macros.h"
11 #include "base/metrics/histogram_base.h"
12 #include "base/test/metrics/histogram_tester.h"
13 #include "components/page_load_metrics/browser/observers/page_load_metrics_observer_content_test_harness.h"
14 #include "components/page_load_metrics/browser/page_load_tracker.h"
15 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
16 #include "url/gurl.h"
17 
18 namespace {
19 
20 const char kTestUrl[] = "https://www.google.com";
21 using WebFeature = blink::mojom::WebFeature;
22 using CSSSampleId = blink::mojom::CSSSampleId;
23 
24 }  // namespace
25 
26 class UseCounterPageLoadMetricsObserverTest
27     : public page_load_metrics::PageLoadMetricsObserverContentTestHarness {
28  public:
UseCounterPageLoadMetricsObserverTest()29   UseCounterPageLoadMetricsObserverTest() {}
30 
HistogramBasicTest(const page_load_metrics::mojom::PageLoadFeatures & first_features,const page_load_metrics::mojom::PageLoadFeatures & second_features=page_load_metrics::mojom::PageLoadFeatures ())31   void HistogramBasicTest(
32       const page_load_metrics::mojom::PageLoadFeatures& first_features,
33       const page_load_metrics::mojom::PageLoadFeatures& second_features =
34           page_load_metrics::mojom::PageLoadFeatures()) {
35     NavigateAndCommit(GURL(kTestUrl));
36     tester()->SimulateFeaturesUpdate(first_features);
37     // Verify that kPageVisits is observed on commit.
38     tester()->histogram_tester().ExpectBucketCount(
39         internal::kFeaturesHistogramName,
40         static_cast<base::Histogram::Sample>(WebFeature::kPageVisits), 1);
41     tester()->histogram_tester().ExpectBucketCount(
42         internal::kFeaturesHistogramMainFrameName,
43         static_cast<base::Histogram::Sample>(WebFeature::kPageVisits), 1);
44     // Verify that page visit is recorded for CSS histograms.
45     tester()->histogram_tester().ExpectBucketCount(
46         internal::kCssPropertiesHistogramName,
47         blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
48     tester()->histogram_tester().ExpectBucketCount(
49         internal::kAnimatedCssPropertiesHistogramName,
50         blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
51 
52     for (auto feature : first_features.features) {
53       tester()->histogram_tester().ExpectBucketCount(
54           internal::kFeaturesHistogramName,
55           static_cast<base::Histogram::Sample>(feature), 1);
56       tester()->histogram_tester().ExpectBucketCount(
57           internal::kFeaturesHistogramMainFrameName,
58           static_cast<base::Histogram::Sample>(feature), 1);
59     }
60 
61     tester()->SimulateFeaturesUpdate(second_features);
62     for (auto feature : first_features.features) {
63       tester()->histogram_tester().ExpectBucketCount(
64           internal::kFeaturesHistogramName,
65           static_cast<base::Histogram::Sample>(feature), 1);
66       tester()->histogram_tester().ExpectBucketCount(
67           internal::kFeaturesHistogramMainFrameName,
68           static_cast<base::Histogram::Sample>(feature), 1);
69     }
70     for (auto feature : second_features.features) {
71       tester()->histogram_tester().ExpectBucketCount(
72           internal::kFeaturesHistogramName,
73           static_cast<base::Histogram::Sample>(feature), 1);
74       tester()->histogram_tester().ExpectBucketCount(
75           internal::kFeaturesHistogramMainFrameName,
76           static_cast<base::Histogram::Sample>(feature), 1);
77     }
78   }
79 
CssHistogramBasicTest(const page_load_metrics::mojom::PageLoadFeatures & first_features,const page_load_metrics::mojom::PageLoadFeatures & second_features=page_load_metrics::mojom::PageLoadFeatures ())80   void CssHistogramBasicTest(
81       const page_load_metrics::mojom::PageLoadFeatures& first_features,
82       const page_load_metrics::mojom::PageLoadFeatures& second_features =
83           page_load_metrics::mojom::PageLoadFeatures()) {
84     NavigateAndCommit(GURL(kTestUrl));
85     tester()->SimulateFeaturesUpdate(first_features);
86     // Verify that page visit is recorded for CSS histograms.
87     tester()->histogram_tester().ExpectBucketCount(
88         internal::kCssPropertiesHistogramName,
89         blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
90 
91     for (auto feature : first_features.css_properties) {
92       tester()->histogram_tester().ExpectBucketCount(
93           internal::kCssPropertiesHistogramName, feature, 1);
94     }
95 
96     tester()->SimulateFeaturesUpdate(second_features);
97     for (auto feature : first_features.css_properties) {
98       tester()->histogram_tester().ExpectBucketCount(
99           internal::kCssPropertiesHistogramName, feature, 1);
100     }
101     for (auto feature : second_features.css_properties) {
102       tester()->histogram_tester().ExpectBucketCount(
103           internal::kCssPropertiesHistogramName, feature, 1);
104     }
105   }
106 
AnimatedCssHistogramBasicTest(const page_load_metrics::mojom::PageLoadFeatures & first_features,const page_load_metrics::mojom::PageLoadFeatures & second_features=page_load_metrics::mojom::PageLoadFeatures ())107   void AnimatedCssHistogramBasicTest(
108       const page_load_metrics::mojom::PageLoadFeatures& first_features,
109       const page_load_metrics::mojom::PageLoadFeatures& second_features =
110           page_load_metrics::mojom::PageLoadFeatures()) {
111     NavigateAndCommit(GURL(kTestUrl));
112     tester()->SimulateFeaturesUpdate(first_features);
113     // Verify that page visit is recorded for CSS histograms.
114     tester()->histogram_tester().ExpectBucketCount(
115         internal::kAnimatedCssPropertiesHistogramName,
116         blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
117 
118     for (auto feature : first_features.animated_css_properties) {
119       tester()->histogram_tester().ExpectBucketCount(
120           internal::kAnimatedCssPropertiesHistogramName, feature, 1);
121     }
122 
123     tester()->SimulateFeaturesUpdate(second_features);
124     for (auto feature : first_features.animated_css_properties) {
125       tester()->histogram_tester().ExpectBucketCount(
126           internal::kAnimatedCssPropertiesHistogramName, feature, 1);
127     }
128     for (auto feature : second_features.animated_css_properties) {
129       tester()->histogram_tester().ExpectBucketCount(
130           internal::kAnimatedCssPropertiesHistogramName, feature, 1);
131     }
132   }
133 
134  protected:
RegisterObservers(page_load_metrics::PageLoadTracker * tracker)135   void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
136     tracker->AddObserver(std::make_unique<UseCounterPageLoadMetricsObserver>());
137   }
138 
139  private:
140   DISALLOW_COPY_AND_ASSIGN(UseCounterPageLoadMetricsObserverTest);
141 };
142 
TEST_F(UseCounterPageLoadMetricsObserverTest,CountOneFeature)143 TEST_F(UseCounterPageLoadMetricsObserverTest, CountOneFeature) {
144   std::vector<WebFeature> features({WebFeature::kFetch});
145   page_load_metrics::mojom::PageLoadFeatures page_load_features;
146   page_load_features.features = features;
147   HistogramBasicTest(page_load_features);
148 }
149 
TEST_F(UseCounterPageLoadMetricsObserverTest,CountFeatures)150 TEST_F(UseCounterPageLoadMetricsObserverTest, CountFeatures) {
151   std::vector<WebFeature> features_0(
152       {WebFeature::kFetch, WebFeature::kFetchBodyStream});
153   std::vector<WebFeature> features_1({WebFeature::kWindowFind});
154   page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
155   page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
156   page_load_features_0.features = features_0;
157   page_load_features_1.features = features_1;
158   HistogramBasicTest(page_load_features_0, page_load_features_1);
159 }
160 
TEST_F(UseCounterPageLoadMetricsObserverTest,CountDuplicatedFeatures)161 TEST_F(UseCounterPageLoadMetricsObserverTest, CountDuplicatedFeatures) {
162   std::vector<WebFeature> features_0(
163       {WebFeature::kFetch, WebFeature::kFetch, WebFeature::kFetchBodyStream});
164   std::vector<WebFeature> features_1(
165       {WebFeature::kFetch, WebFeature::kWindowFind});
166   page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
167   page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
168   page_load_features_0.features = features_0;
169   page_load_features_1.features = features_1;
170   HistogramBasicTest(page_load_features_0, page_load_features_1);
171 }
172 
TEST_F(UseCounterPageLoadMetricsObserverTest,RecordCSSProperties)173 TEST_F(UseCounterPageLoadMetricsObserverTest, RecordCSSProperties) {
174   // CSSPropertyID::kFont (5), CSSPropertyID::kZoom (19)
175   page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
176   page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
177   page_load_features_0.css_properties = {CSSSampleId::kFont,
178                                          CSSSampleId::kZoom};
179   page_load_features_1.css_properties = {CSSSampleId::kZoom};
180   CssHistogramBasicTest(page_load_features_0, page_load_features_1);
181 }
182 
TEST_F(UseCounterPageLoadMetricsObserverTest,RecordAnimatedCSSProperties)183 TEST_F(UseCounterPageLoadMetricsObserverTest, RecordAnimatedCSSProperties) {
184   page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
185   page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
186   page_load_features_0.css_properties = {CSSSampleId::kFont,
187                                          CSSSampleId::kZoom};
188   page_load_features_1.css_properties = {CSSSampleId::kZoom};
189   AnimatedCssHistogramBasicTest(page_load_features_0, page_load_features_1);
190 }
191 
TEST_F(UseCounterPageLoadMetricsObserverTest,RecordCSSPropertiesInRange)192 TEST_F(UseCounterPageLoadMetricsObserverTest, RecordCSSPropertiesInRange) {
193   page_load_metrics::mojom::PageLoadFeatures page_load_features;
194   page_load_features.css_properties = {CSSSampleId::kColor,
195                                        CSSSampleId::kMaxValue};
196   CssHistogramBasicTest(page_load_features);
197 }
198