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 "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" | 5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 const char kDefaultTestUrl[] = "https://google.com/"; | 33 const char kDefaultTestUrl[] = "https://google.com/"; |
34 const char kDefaultTestUrlAnchor[] = "https://google.com/#samedocument"; | 34 const char kDefaultTestUrlAnchor[] = "https://google.com/#samedocument"; |
35 const char kDefaultTestUrl2[] = "https://whatever.com/"; | 35 const char kDefaultTestUrl2[] = "https://whatever.com/"; |
36 const char kFilteredStartUrl[] = "https://whatever.com/ignore-on-start"; | 36 const char kFilteredStartUrl[] = "https://whatever.com/ignore-on-start"; |
37 const char kFilteredCommitUrl[] = "https://whatever.com/ignore-on-commit"; | 37 const char kFilteredCommitUrl[] = "https://whatever.com/ignore-on-commit"; |
38 | 38 |
39 // Simple PageLoadMetricsObserver that copies observed PageLoadTimings into the | 39 // Simple PageLoadMetricsObserver that copies observed PageLoadTimings into the |
40 // provided std::vector, so they can be analyzed by unit tests. | 40 // provided std::vector, so they can be analyzed by unit tests. |
41 class TestPageLoadMetricsObserver : public PageLoadMetricsObserver { | 41 class TestPageLoadMetricsObserver : public PageLoadMetricsObserver { |
42 public: | 42 public: |
43 TestPageLoadMetricsObserver(std::vector<PageLoadTiming>* updated_timings, | 43 TestPageLoadMetricsObserver( |
44 std::vector<PageLoadTiming>* complete_timings, | 44 std::vector<PageLoadTiming>* updated_timings, |
45 std::vector<GURL>* observed_committed_urls) | 45 std::vector<PageLoadTiming>* updated_sub_frame_timings, |
| 46 std::vector<PageLoadTiming>* complete_timings, |
| 47 std::vector<GURL>* observed_committed_urls) |
46 : updated_timings_(updated_timings), | 48 : updated_timings_(updated_timings), |
| 49 updated_sub_frame_timings_(updated_sub_frame_timings), |
47 complete_timings_(complete_timings), | 50 complete_timings_(complete_timings), |
48 observed_committed_urls_(observed_committed_urls) {} | 51 observed_committed_urls_(observed_committed_urls) {} |
49 | 52 |
50 ObservePolicy OnStart(content::NavigationHandle* navigation_handle, | 53 ObservePolicy OnStart(content::NavigationHandle* navigation_handle, |
51 const GURL& currently_committed_url, | 54 const GURL& currently_committed_url, |
52 bool started_in_foreground) override { | 55 bool started_in_foreground) override { |
53 observed_committed_urls_->push_back(currently_committed_url); | 56 observed_committed_urls_->push_back(currently_committed_url); |
54 return CONTINUE_OBSERVING; | 57 return CONTINUE_OBSERVING; |
55 } | 58 } |
56 | 59 |
57 void OnTimingUpdate(const PageLoadTiming& timing, | 60 void OnTimingUpdate(const PageLoadTiming& timing, |
58 const PageLoadExtraInfo& extra_info) override { | 61 const PageLoadExtraInfo& extra_info) override { |
59 updated_timings_->push_back(timing); | 62 updated_timings_->push_back(timing); |
60 } | 63 } |
61 | 64 |
| 65 void OnSubFrameTimingUpdate(FrameTreeNodeId child_frame_id, |
| 66 base::TimeDelta navigation_start, |
| 67 const PageLoadTiming& child_timing, |
| 68 const PageLoadMetadata& child_metadata, |
| 69 const PageLoadExtraInfo& extra_info) override { |
| 70 updated_sub_frame_timings_->push_back(child_timing); |
| 71 } |
| 72 |
62 void OnComplete(const PageLoadTiming& timing, | 73 void OnComplete(const PageLoadTiming& timing, |
63 const PageLoadExtraInfo& extra_info) override { | 74 const PageLoadExtraInfo& extra_info) override { |
64 complete_timings_->push_back(timing); | 75 complete_timings_->push_back(timing); |
65 } | 76 } |
66 | 77 |
67 ObservePolicy FlushMetricsOnAppEnterBackground( | 78 ObservePolicy FlushMetricsOnAppEnterBackground( |
68 const PageLoadTiming& timing, | 79 const PageLoadTiming& timing, |
69 const PageLoadExtraInfo& extra_info) override { | 80 const PageLoadExtraInfo& extra_info) override { |
70 return STOP_OBSERVING; | 81 return STOP_OBSERVING; |
71 } | 82 } |
72 | 83 |
73 private: | 84 private: |
74 std::vector<PageLoadTiming>* const updated_timings_; | 85 std::vector<PageLoadTiming>* const updated_timings_; |
| 86 std::vector<PageLoadTiming>* const updated_sub_frame_timings_; |
75 std::vector<PageLoadTiming>* const complete_timings_; | 87 std::vector<PageLoadTiming>* const complete_timings_; |
76 std::vector<GURL>* const observed_committed_urls_; | 88 std::vector<GURL>* const observed_committed_urls_; |
77 }; | 89 }; |
78 | 90 |
79 // Test PageLoadMetricsObserver that stops observing page loads with certain | 91 // Test PageLoadMetricsObserver that stops observing page loads with certain |
80 // substrings in the URL. | 92 // substrings in the URL. |
81 class FilteringPageLoadMetricsObserver : public PageLoadMetricsObserver { | 93 class FilteringPageLoadMetricsObserver : public PageLoadMetricsObserver { |
82 public: | 94 public: |
83 explicit FilteringPageLoadMetricsObserver( | 95 explicit FilteringPageLoadMetricsObserver( |
84 std::vector<GURL>* completed_filtered_urls) | 96 std::vector<GURL>* completed_filtered_urls) |
(...skipping 24 matching lines...) Expand all Loading... |
109 | 121 |
110 class TestPageLoadMetricsEmbedderInterface | 122 class TestPageLoadMetricsEmbedderInterface |
111 : public PageLoadMetricsEmbedderInterface { | 123 : public PageLoadMetricsEmbedderInterface { |
112 public: | 124 public: |
113 TestPageLoadMetricsEmbedderInterface() : is_ntp_(false) {} | 125 TestPageLoadMetricsEmbedderInterface() : is_ntp_(false) {} |
114 | 126 |
115 bool IsNewTabPageUrl(const GURL& url) override { return is_ntp_; } | 127 bool IsNewTabPageUrl(const GURL& url) override { return is_ntp_; } |
116 void set_is_ntp(bool is_ntp) { is_ntp_ = is_ntp; } | 128 void set_is_ntp(bool is_ntp) { is_ntp_ = is_ntp; } |
117 void RegisterObservers(PageLoadTracker* tracker) override { | 129 void RegisterObservers(PageLoadTracker* tracker) override { |
118 tracker->AddObserver(base::MakeUnique<TestPageLoadMetricsObserver>( | 130 tracker->AddObserver(base::MakeUnique<TestPageLoadMetricsObserver>( |
119 &updated_timings_, &complete_timings_, &observed_committed_urls_)); | 131 &updated_timings_, &updated_sub_frame_timings_, &complete_timings_, |
| 132 &observed_committed_urls_)); |
120 tracker->AddObserver(base::MakeUnique<FilteringPageLoadMetricsObserver>( | 133 tracker->AddObserver(base::MakeUnique<FilteringPageLoadMetricsObserver>( |
121 &completed_filtered_urls_)); | 134 &completed_filtered_urls_)); |
122 } | 135 } |
123 const std::vector<PageLoadTiming>& updated_timings() const { | 136 const std::vector<PageLoadTiming>& updated_timings() const { |
124 return updated_timings_; | 137 return updated_timings_; |
125 } | 138 } |
126 const std::vector<PageLoadTiming>& complete_timings() const { | 139 const std::vector<PageLoadTiming>& complete_timings() const { |
127 return complete_timings_; | 140 return complete_timings_; |
128 } | 141 } |
| 142 const std::vector<PageLoadTiming>& updated_subframe_timings() const { |
| 143 return updated_sub_frame_timings_; |
| 144 } |
129 | 145 |
130 // currently_committed_urls passed to OnStart(). | 146 // currently_committed_urls passed to OnStart(). |
131 const std::vector<GURL>& observed_committed_urls_from_on_start() const { | 147 const std::vector<GURL>& observed_committed_urls_from_on_start() const { |
132 return observed_committed_urls_; | 148 return observed_committed_urls_; |
133 } | 149 } |
134 | 150 |
135 // committed URLs passed to FilteringPageLoadMetricsObserver::OnComplete(). | 151 // committed URLs passed to FilteringPageLoadMetricsObserver::OnComplete(). |
136 const std::vector<GURL>& completed_filtered_urls() const { | 152 const std::vector<GURL>& completed_filtered_urls() const { |
137 return completed_filtered_urls_; | 153 return completed_filtered_urls_; |
138 } | 154 } |
139 | 155 |
140 private: | 156 private: |
141 std::vector<PageLoadTiming> updated_timings_; | 157 std::vector<PageLoadTiming> updated_timings_; |
| 158 std::vector<PageLoadTiming> updated_sub_frame_timings_; |
142 std::vector<PageLoadTiming> complete_timings_; | 159 std::vector<PageLoadTiming> complete_timings_; |
143 std::vector<GURL> observed_committed_urls_; | 160 std::vector<GURL> observed_committed_urls_; |
144 std::vector<GURL> completed_filtered_urls_; | 161 std::vector<GURL> completed_filtered_urls_; |
145 bool is_ntp_; | 162 bool is_ntp_; |
146 }; | 163 }; |
147 | 164 |
148 } // namespace | 165 } // namespace |
149 | 166 |
150 class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness { | 167 class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness { |
151 public: | 168 public: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 | 213 |
197 int CountEmptyCompleteTimingReported() { | 214 int CountEmptyCompleteTimingReported() { |
198 int empty = 0; | 215 int empty = 0; |
199 for (const auto& timing : embedder_interface_->complete_timings()) { | 216 for (const auto& timing : embedder_interface_->complete_timings()) { |
200 if (timing.IsEmpty()) | 217 if (timing.IsEmpty()) |
201 ++empty; | 218 ++empty; |
202 } | 219 } |
203 return empty; | 220 return empty; |
204 } | 221 } |
205 | 222 |
206 int CountCompleteTimingReported() { | 223 const std::vector<PageLoadTiming>& updated_timings() const { |
207 return embedder_interface_->complete_timings().size(); | 224 return embedder_interface_->updated_timings(); |
208 } | 225 } |
209 int CountUpdatedTimingReported() { | 226 const std::vector<PageLoadTiming>& complete_timings() const { |
210 return embedder_interface_->updated_timings().size(); | 227 return embedder_interface_->complete_timings(); |
| 228 } |
| 229 const std::vector<PageLoadTiming>& updated_subframe_timings() const { |
| 230 return embedder_interface_->updated_subframe_timings(); |
| 231 } |
| 232 int CountCompleteTimingReported() { return complete_timings().size(); } |
| 233 int CountUpdatedTimingReported() { return updated_timings().size(); } |
| 234 int CountUpdatedSubFrameTimingReported() { |
| 235 return updated_subframe_timings().size(); |
211 } | 236 } |
212 | 237 |
213 const std::vector<GURL>& observed_committed_urls_from_on_start() const { | 238 const std::vector<GURL>& observed_committed_urls_from_on_start() const { |
214 return embedder_interface_->observed_committed_urls_from_on_start(); | 239 return embedder_interface_->observed_committed_urls_from_on_start(); |
215 } | 240 } |
216 | 241 |
217 const std::vector<GURL>& completed_filtered_urls() const { | 242 const std::vector<GURL>& completed_filtered_urls() const { |
218 return embedder_interface_->completed_filtered_urls(); | 243 return embedder_interface_->completed_filtered_urls(); |
219 } | 244 } |
220 | 245 |
(...skipping 25 matching lines...) Expand all Loading... |
246 ASSERT_EQ(1, CountUpdatedTimingReported()); | 271 ASSERT_EQ(1, CountUpdatedTimingReported()); |
247 ASSERT_EQ(0, CountCompleteTimingReported()); | 272 ASSERT_EQ(0, CountCompleteTimingReported()); |
248 | 273 |
249 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 274 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |
250 ASSERT_EQ(1, CountCompleteTimingReported()); | 275 ASSERT_EQ(1, CountCompleteTimingReported()); |
251 ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | 276 ASSERT_EQ(0, CountEmptyCompleteTimingReported()); |
252 ASSERT_EQ(2u, observed_committed_urls_from_on_start().size()); | 277 ASSERT_EQ(2u, observed_committed_urls_from_on_start().size()); |
253 ASSERT_EQ(kDefaultTestUrl, | 278 ASSERT_EQ(kDefaultTestUrl, |
254 observed_committed_urls_from_on_start().at(1).spec()); | 279 observed_committed_urls_from_on_start().at(1).spec()); |
255 ASSERT_EQ(1, CountUpdatedTimingReported()); | 280 ASSERT_EQ(1, CountUpdatedTimingReported()); |
| 281 ASSERT_EQ(0, CountUpdatedSubFrameTimingReported()); |
256 | 282 |
257 CheckNoErrorEvents(); | 283 CheckNoErrorEvents(); |
258 } | 284 } |
259 | 285 |
260 TEST_F(MetricsWebContentsObserverTest, NotInMainFrame) { | 286 TEST_F(MetricsWebContentsObserverTest, SubFrame) { |
261 PageLoadTiming timing; | 287 PageLoadTiming timing; |
262 timing.navigation_start = base::Time::FromDoubleT(1); | 288 timing.navigation_start = base::Time::FromDoubleT(1); |
263 | 289 |
264 content::WebContentsTester* web_contents_tester = | 290 content::WebContentsTester* web_contents_tester = |
265 content::WebContentsTester::For(web_contents()); | 291 content::WebContentsTester::For(web_contents()); |
266 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 292 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |
| 293 SimulateTimingUpdate(timing); |
267 | 294 |
268 content::RenderFrameHostTester* rfh_tester = | 295 content::RenderFrameHostTester* rfh_tester = |
269 content::RenderFrameHostTester::For(main_rfh()); | 296 content::RenderFrameHostTester::For(main_rfh()); |
270 content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); | 297 content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); |
271 | 298 |
| 299 PageLoadTiming subframe_timing; |
| 300 subframe_timing.navigation_start = base::Time::FromDoubleT(2); |
272 content::RenderFrameHostTester* subframe_tester = | 301 content::RenderFrameHostTester* subframe_tester = |
273 content::RenderFrameHostTester::For(subframe); | 302 content::RenderFrameHostTester::For(subframe); |
274 subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); | 303 subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); |
275 subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); | 304 subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); |
276 SimulateTimingUpdate(timing, subframe); | 305 SimulateTimingUpdate(subframe_timing, subframe); |
277 subframe_tester->SimulateNavigationStop(); | 306 subframe_tester->SimulateNavigationStop(); |
278 | 307 |
279 // Navigate again to see if the timing updated for a subframe message. | 308 // Navigate again to see if the timing updated for a subframe message. |
280 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 309 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |
281 | 310 |
282 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
283 ASSERT_EQ(1, CountCompleteTimingReported()); | 311 ASSERT_EQ(1, CountCompleteTimingReported()); |
284 ASSERT_EQ(1, CountEmptyCompleteTimingReported()); | 312 ASSERT_EQ(1, CountUpdatedTimingReported()); |
285 CheckErrorEvent(ERR_TIMING_IPC_FROM_SUBFRAME, 1); | 313 ASSERT_EQ(0, CountEmptyCompleteTimingReported()); |
286 CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); | 314 EXPECT_EQ(timing, updated_timings().at(0)); |
287 CheckTotalErrorEvents(); | 315 |
| 316 ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); |
| 317 EXPECT_EQ(subframe_timing, updated_subframe_timings().at(0)); |
| 318 |
| 319 CheckNoErrorEvents(); |
288 } | 320 } |
289 | 321 |
290 TEST_F(MetricsWebContentsObserverTest, SameDocumentNoTrigger) { | 322 TEST_F(MetricsWebContentsObserverTest, SameDocumentNoTrigger) { |
291 PageLoadTiming timing; | 323 PageLoadTiming timing; |
292 timing.navigation_start = base::Time::FromDoubleT(1); | 324 timing.navigation_start = base::Time::FromDoubleT(1); |
293 | 325 |
294 content::WebContentsTester* web_contents_tester = | 326 content::WebContentsTester* web_contents_tester = |
295 content::WebContentsTester::For(web_contents()); | 327 content::WebContentsTester::For(web_contents()); |
296 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 328 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |
297 ASSERT_EQ(0, CountUpdatedTimingReported()); | 329 ASSERT_EQ(0, CountUpdatedTimingReported()); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); | 454 CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); |
423 CheckTotalErrorEvents(); | 455 CheckTotalErrorEvents(); |
424 | 456 |
425 histogram_tester_.ExpectTotalCount( | 457 histogram_tester_.ExpectTotalCount( |
426 page_load_metrics::internal::kPageLoadTimingStatus, 1); | 458 page_load_metrics::internal::kPageLoadTimingStatus, 1); |
427 histogram_tester_.ExpectBucketCount( | 459 histogram_tester_.ExpectBucketCount( |
428 page_load_metrics::internal::kPageLoadTimingStatus, | 460 page_load_metrics::internal::kPageLoadTimingStatus, |
429 page_load_metrics::internal::INVALID_ORDER_PARSE_START_PARSE_STOP, 1); | 461 page_load_metrics::internal::INVALID_ORDER_PARSE_START_PARSE_STOP, 1); |
430 } | 462 } |
431 | 463 |
432 TEST_F(MetricsWebContentsObserverTest, NotInMainError) { | |
433 PageLoadTiming timing; | |
434 timing.navigation_start = base::Time::FromDoubleT(1); | |
435 | |
436 content::WebContentsTester* web_contents_tester = | |
437 content::WebContentsTester::For(web_contents()); | |
438 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
439 | |
440 content::RenderFrameHostTester* rfh_tester = | |
441 content::RenderFrameHostTester::For(main_rfh()); | |
442 content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); | |
443 | |
444 content::RenderFrameHostTester* subframe_tester = | |
445 content::RenderFrameHostTester::For(subframe); | |
446 subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); | |
447 subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); | |
448 SimulateTimingUpdate(timing, subframe); | |
449 CheckErrorEvent(ERR_TIMING_IPC_FROM_SUBFRAME, 1); | |
450 CheckTotalErrorEvents(); | |
451 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
452 ASSERT_EQ(0, CountCompleteTimingReported()); | |
453 } | |
454 | |
455 TEST_F(MetricsWebContentsObserverTest, BadIPC) { | 464 TEST_F(MetricsWebContentsObserverTest, BadIPC) { |
456 PageLoadTiming timing; | 465 PageLoadTiming timing; |
457 timing.navigation_start = base::Time::FromDoubleT(10); | 466 timing.navigation_start = base::Time::FromDoubleT(10); |
458 PageLoadTiming timing2; | 467 PageLoadTiming timing2; |
459 timing2.navigation_start = base::Time::FromDoubleT(100); | 468 timing2.navigation_start = base::Time::FromDoubleT(100); |
460 | 469 |
461 content::WebContentsTester* web_contents_tester = | 470 content::WebContentsTester* web_contents_tester = |
462 content::WebContentsTester::For(web_contents()); | 471 content::WebContentsTester::For(web_contents()); |
463 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 472 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |
464 | 473 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 672 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |
664 ASSERT_EQ(std::vector<GURL>({GURL(kDefaultTestUrl)}), | 673 ASSERT_EQ(std::vector<GURL>({GURL(kDefaultTestUrl)}), |
665 completed_filtered_urls()); | 674 completed_filtered_urls()); |
666 | 675 |
667 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 676 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |
668 ASSERT_EQ(std::vector<GURL>({GURL(kDefaultTestUrl), GURL(kDefaultTestUrl2)}), | 677 ASSERT_EQ(std::vector<GURL>({GURL(kDefaultTestUrl), GURL(kDefaultTestUrl2)}), |
669 completed_filtered_urls()); | 678 completed_filtered_urls()); |
670 } | 679 } |
671 | 680 |
672 } // namespace page_load_metrics | 681 } // namespace page_load_metrics |
OLD | NEW |