| 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 20 matching lines...) Expand all Loading... |
| 31 namespace { | 31 namespace { |
| 32 | 32 |
| 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 | 41 class TestPageLoadMetricsObserver : public PageLoadMetricsObserver { |
| 42 : public PageLoadMetricsObserver, | |
| 43 public MetricsWebContentsObserver::TestingObserver { | |
| 44 public: | 42 public: |
| 45 TestPageLoadMetricsObserver( | 43 TestPageLoadMetricsObserver( |
| 46 content::WebContents* web_contents, | |
| 47 std::vector<mojom::PageLoadTimingPtr>* updated_timings, | 44 std::vector<mojom::PageLoadTimingPtr>* updated_timings, |
| 48 std::vector<mojom::PageLoadTimingPtr>* updated_subframe_timings, | 45 std::vector<mojom::PageLoadTimingPtr>* updated_subframe_timings, |
| 49 std::vector<mojom::PageLoadTimingPtr>* complete_timings, | 46 std::vector<mojom::PageLoadTimingPtr>* complete_timings, |
| 50 std::vector<GURL>* observed_committed_urls) | 47 std::vector<GURL>* observed_committed_urls) |
| 51 : MetricsWebContentsObserver::TestingObserver(web_contents), | 48 : updated_timings_(updated_timings), |
| 52 updated_timings_(updated_timings), | |
| 53 updated_subframe_timings_(updated_subframe_timings), | 49 updated_subframe_timings_(updated_subframe_timings), |
| 54 complete_timings_(complete_timings), | 50 complete_timings_(complete_timings), |
| 55 observed_committed_urls_(observed_committed_urls) {} | 51 observed_committed_urls_(observed_committed_urls) {} |
| 56 | 52 |
| 57 ObservePolicy OnStart(content::NavigationHandle* navigation_handle, | 53 ObservePolicy OnStart(content::NavigationHandle* navigation_handle, |
| 58 const GURL& currently_committed_url, | 54 const GURL& currently_committed_url, |
| 59 bool started_in_foreground) override { | 55 bool started_in_foreground) override { |
| 60 observed_committed_urls_->push_back(currently_committed_url); | 56 observed_committed_urls_->push_back(currently_committed_url); |
| 61 return CONTINUE_OBSERVING; | 57 return CONTINUE_OBSERVING; |
| 62 } | 58 } |
| 63 | 59 |
| 64 void OnTimingUpdate(const mojom::PageLoadTiming& timing, | 60 void OnTimingUpdate(bool is_subframe, |
| 61 const mojom::PageLoadTiming& timing, |
| 65 const PageLoadExtraInfo& extra_info) override { | 62 const PageLoadExtraInfo& extra_info) override { |
| 66 updated_timings_->push_back(timing.Clone()); | 63 if (is_subframe) |
| 67 } | |
| 68 | |
| 69 void OnTimingUpdated(bool is_main_frame, | |
| 70 const mojom::PageLoadTiming& timing, | |
| 71 const mojom::PageLoadMetadata& metadata) override { | |
| 72 if (!is_main_frame) { | |
| 73 updated_subframe_timings_->push_back(timing.Clone()); | 64 updated_subframe_timings_->push_back(timing.Clone()); |
| 74 } | 65 else |
| 66 updated_timings_->push_back(timing.Clone()); |
| 75 } | 67 } |
| 76 | 68 |
| 77 void OnComplete(const mojom::PageLoadTiming& timing, | 69 void OnComplete(const mojom::PageLoadTiming& timing, |
| 78 const PageLoadExtraInfo& extra_info) override { | 70 const PageLoadExtraInfo& extra_info) override { |
| 79 complete_timings_->push_back(timing.Clone()); | 71 complete_timings_->push_back(timing.Clone()); |
| 80 } | 72 } |
| 81 | 73 |
| 82 ObservePolicy FlushMetricsOnAppEnterBackground( | 74 ObservePolicy FlushMetricsOnAppEnterBackground( |
| 83 const mojom::PageLoadTiming& timing, | 75 const mojom::PageLoadTiming& timing, |
| 84 const PageLoadExtraInfo& extra_info) override { | 76 const PageLoadExtraInfo& extra_info) override { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 completed_filtered_urls_->push_back(extra_info.url); | 111 completed_filtered_urls_->push_back(extra_info.url); |
| 120 } | 112 } |
| 121 | 113 |
| 122 private: | 114 private: |
| 123 std::vector<GURL>* const completed_filtered_urls_; | 115 std::vector<GURL>* const completed_filtered_urls_; |
| 124 }; | 116 }; |
| 125 | 117 |
| 126 class TestPageLoadMetricsEmbedderInterface | 118 class TestPageLoadMetricsEmbedderInterface |
| 127 : public PageLoadMetricsEmbedderInterface { | 119 : public PageLoadMetricsEmbedderInterface { |
| 128 public: | 120 public: |
| 129 explicit TestPageLoadMetricsEmbedderInterface( | 121 TestPageLoadMetricsEmbedderInterface() : is_ntp_(false) {} |
| 130 content::WebContents* web_contents) | |
| 131 : web_contents_(web_contents), is_ntp_(false) {} | |
| 132 | 122 |
| 133 bool IsNewTabPageUrl(const GURL& url) override { return is_ntp_; } | 123 bool IsNewTabPageUrl(const GURL& url) override { return is_ntp_; } |
| 134 void set_is_ntp(bool is_ntp) { is_ntp_ = is_ntp; } | 124 void set_is_ntp(bool is_ntp) { is_ntp_ = is_ntp; } |
| 135 void RegisterObservers(PageLoadTracker* tracker) override { | 125 void RegisterObservers(PageLoadTracker* tracker) override { |
| 136 tracker->AddObserver(base::MakeUnique<TestPageLoadMetricsObserver>( | 126 tracker->AddObserver(base::MakeUnique<TestPageLoadMetricsObserver>( |
| 137 web_contents_, &updated_timings_, &updated_subframe_timings_, | 127 &updated_timings_, &updated_subframe_timings_, &complete_timings_, |
| 138 &complete_timings_, &observed_committed_urls_)); | 128 &observed_committed_urls_)); |
| 139 tracker->AddObserver(base::MakeUnique<FilteringPageLoadMetricsObserver>( | 129 tracker->AddObserver(base::MakeUnique<FilteringPageLoadMetricsObserver>( |
| 140 &completed_filtered_urls_)); | 130 &completed_filtered_urls_)); |
| 141 } | 131 } |
| 142 const std::vector<mojom::PageLoadTimingPtr>& updated_timings() const { | 132 const std::vector<mojom::PageLoadTimingPtr>& updated_timings() const { |
| 143 return updated_timings_; | 133 return updated_timings_; |
| 144 } | 134 } |
| 145 const std::vector<mojom::PageLoadTimingPtr>& complete_timings() const { | 135 const std::vector<mojom::PageLoadTimingPtr>& complete_timings() const { |
| 146 return complete_timings_; | 136 return complete_timings_; |
| 147 } | 137 } |
| 148 const std::vector<mojom::PageLoadTimingPtr>& updated_subframe_timings() | 138 const std::vector<mojom::PageLoadTimingPtr>& updated_subframe_timings() |
| (...skipping 10 matching lines...) Expand all Loading... |
| 159 const std::vector<GURL>& completed_filtered_urls() const { | 149 const std::vector<GURL>& completed_filtered_urls() const { |
| 160 return completed_filtered_urls_; | 150 return completed_filtered_urls_; |
| 161 } | 151 } |
| 162 | 152 |
| 163 private: | 153 private: |
| 164 std::vector<mojom::PageLoadTimingPtr> updated_timings_; | 154 std::vector<mojom::PageLoadTimingPtr> updated_timings_; |
| 165 std::vector<mojom::PageLoadTimingPtr> updated_subframe_timings_; | 155 std::vector<mojom::PageLoadTimingPtr> updated_subframe_timings_; |
| 166 std::vector<mojom::PageLoadTimingPtr> complete_timings_; | 156 std::vector<mojom::PageLoadTimingPtr> complete_timings_; |
| 167 std::vector<GURL> observed_committed_urls_; | 157 std::vector<GURL> observed_committed_urls_; |
| 168 std::vector<GURL> completed_filtered_urls_; | 158 std::vector<GURL> completed_filtered_urls_; |
| 169 content::WebContents* web_contents_; | |
| 170 bool is_ntp_; | 159 bool is_ntp_; |
| 171 }; | 160 }; |
| 172 | 161 |
| 173 } // namespace | 162 } // namespace |
| 174 | 163 |
| 175 class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness { | 164 class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness { |
| 176 public: | 165 public: |
| 177 MetricsWebContentsObserverTest() : num_errors_(0) {} | 166 MetricsWebContentsObserverTest() : num_errors_(0) {} |
| 178 | 167 |
| 179 void SetUp() override { | 168 void SetUp() override { |
| 180 ChromeRenderViewHostTestHarness::SetUp(); | 169 ChromeRenderViewHostTestHarness::SetUp(); |
| 181 AttachObserver(); | 170 AttachObserver(); |
| 182 } | 171 } |
| 183 | 172 |
| 184 void NavigateToUntrackedUrl() { | 173 void NavigateToUntrackedUrl() { |
| 185 content::WebContentsTester::For(web_contents()) | 174 content::WebContentsTester::For(web_contents()) |
| 186 ->NavigateAndCommit(GURL(url::kAboutBlankURL)); | 175 ->NavigateAndCommit(GURL(url::kAboutBlankURL)); |
| 187 } | 176 } |
| 188 | 177 |
| 189 void SimulateTimingUpdate(const mojom::PageLoadTiming& timing) { | 178 void SimulateTimingUpdate(const mojom::PageLoadTiming& timing) { |
| 190 SimulateTimingUpdate(timing, web_contents()->GetMainFrame()); | 179 SimulateTimingUpdate(timing, web_contents()->GetMainFrame()); |
| 191 } | 180 } |
| 192 | 181 |
| 193 void SimulateTimingUpdate(const mojom::PageLoadTiming& timing, | 182 void SimulateTimingUpdate(const mojom::PageLoadTiming& timing, |
| 194 content::RenderFrameHost* render_frame_host) { | 183 content::RenderFrameHost* render_frame_host) { |
| 195 observer_->OnTimingUpdated(render_frame_host, timing, | 184 observer()->OnTimingUpdated(render_frame_host, timing, |
| 196 mojom::PageLoadMetadata()); | 185 mojom::PageLoadMetadata()); |
| 197 } | 186 } |
| 198 | 187 |
| 199 void AttachObserver() { | 188 void AttachObserver() { |
| 200 embedder_interface_ = | 189 auto embedder_interface = |
| 201 new TestPageLoadMetricsEmbedderInterface(web_contents()); | 190 base::MakeUnique<TestPageLoadMetricsEmbedderInterface>(); |
| 202 // Owned by the web_contents. Tests must be careful not to call | 191 embedder_interface_ = embedder_interface.get(); |
| 203 // SimulateTimingUpdate after they call DeleteContents() without also | 192 MetricsWebContentsObserver* observer = |
| 204 // calling AttachObserver() again. Otherwise they will use-after-free the | 193 MetricsWebContentsObserver::CreateForWebContents( |
| 205 // observer_. | 194 web_contents(), base::nullopt, std::move(embedder_interface)); |
| 206 observer_ = MetricsWebContentsObserver::CreateForWebContents( | 195 observer->WasShown(); |
| 207 web_contents(), base::nullopt, base::WrapUnique(embedder_interface_)); | |
| 208 observer_->WasShown(); | |
| 209 } | 196 } |
| 210 | 197 |
| 211 void CheckErrorEvent(InternalErrorLoadEvent error, int count) { | 198 void CheckErrorEvent(InternalErrorLoadEvent error, int count) { |
| 212 histogram_tester_.ExpectBucketCount(internal::kErrorEvents, error, count); | 199 histogram_tester_.ExpectBucketCount(internal::kErrorEvents, error, count); |
| 213 num_errors_ += count; | 200 num_errors_ += count; |
| 214 } | 201 } |
| 215 | 202 |
| 216 void CheckTotalErrorEvents() { | 203 void CheckTotalErrorEvents() { |
| 217 histogram_tester_.ExpectTotalCount(internal::kErrorEvents, num_errors_); | 204 histogram_tester_.ExpectTotalCount(internal::kErrorEvents, num_errors_); |
| 218 } | 205 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 248 | 235 |
| 249 const std::vector<GURL>& observed_committed_urls_from_on_start() const { | 236 const std::vector<GURL>& observed_committed_urls_from_on_start() const { |
| 250 return embedder_interface_->observed_committed_urls_from_on_start(); | 237 return embedder_interface_->observed_committed_urls_from_on_start(); |
| 251 } | 238 } |
| 252 | 239 |
| 253 const std::vector<GURL>& completed_filtered_urls() const { | 240 const std::vector<GURL>& completed_filtered_urls() const { |
| 254 return embedder_interface_->completed_filtered_urls(); | 241 return embedder_interface_->completed_filtered_urls(); |
| 255 } | 242 } |
| 256 | 243 |
| 257 protected: | 244 protected: |
| 245 MetricsWebContentsObserver* observer() { |
| 246 return MetricsWebContentsObserver::FromWebContents(web_contents()); |
| 247 } |
| 248 |
| 258 base::HistogramTester histogram_tester_; | 249 base::HistogramTester histogram_tester_; |
| 259 TestPageLoadMetricsEmbedderInterface* embedder_interface_; | 250 TestPageLoadMetricsEmbedderInterface* embedder_interface_; |
| 260 MetricsWebContentsObserver* observer_; | |
| 261 | 251 |
| 262 private: | 252 private: |
| 263 int num_errors_; | 253 int num_errors_; |
| 264 | 254 |
| 265 DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserverTest); | 255 DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserverTest); |
| 266 }; | 256 }; |
| 267 | 257 |
| 268 TEST_F(MetricsWebContentsObserverTest, SuccessfulMainFrameNavigation) { | 258 TEST_F(MetricsWebContentsObserverTest, SuccessfulMainFrameNavigation) { |
| 269 mojom::PageLoadTiming timing; | 259 mojom::PageLoadTiming timing; |
| 270 page_load_metrics::InitPageLoadTimingForTest(&timing); | 260 page_load_metrics::InitPageLoadTimingForTest(&timing); |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 } | 631 } |
| 642 | 632 |
| 643 TEST_F(MetricsWebContentsObserverTest, FlushMetricsOnAppEnterBackground) { | 633 TEST_F(MetricsWebContentsObserverTest, FlushMetricsOnAppEnterBackground) { |
| 644 content::WebContentsTester* web_contents_tester = | 634 content::WebContentsTester* web_contents_tester = |
| 645 content::WebContentsTester::For(web_contents()); | 635 content::WebContentsTester::For(web_contents()); |
| 646 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 636 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |
| 647 | 637 |
| 648 histogram_tester_.ExpectTotalCount( | 638 histogram_tester_.ExpectTotalCount( |
| 649 internal::kPageLoadCompletedAfterAppBackground, 0); | 639 internal::kPageLoadCompletedAfterAppBackground, 0); |
| 650 | 640 |
| 651 observer_->FlushMetricsOnAppEnterBackground(); | 641 observer()->FlushMetricsOnAppEnterBackground(); |
| 652 | 642 |
| 653 histogram_tester_.ExpectTotalCount( | 643 histogram_tester_.ExpectTotalCount( |
| 654 internal::kPageLoadCompletedAfterAppBackground, 1); | 644 internal::kPageLoadCompletedAfterAppBackground, 1); |
| 655 histogram_tester_.ExpectBucketCount( | 645 histogram_tester_.ExpectBucketCount( |
| 656 internal::kPageLoadCompletedAfterAppBackground, false, 1); | 646 internal::kPageLoadCompletedAfterAppBackground, false, 1); |
| 657 histogram_tester_.ExpectBucketCount( | 647 histogram_tester_.ExpectBucketCount( |
| 658 internal::kPageLoadCompletedAfterAppBackground, true, 0); | 648 internal::kPageLoadCompletedAfterAppBackground, true, 0); |
| 659 | 649 |
| 660 // Navigate again, which forces completion callbacks on the previous | 650 // Navigate again, which forces completion callbacks on the previous |
| 661 // navigation to be invoked. | 651 // navigation to be invoked. |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 ASSERT_EQ(2, CountUpdatedTimingReported()); | 791 ASSERT_EQ(2, CountUpdatedTimingReported()); |
| 802 ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | 792 ASSERT_EQ(0, CountEmptyCompleteTimingReported()); |
| 803 | 793 |
| 804 ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); | 794 ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); |
| 805 EXPECT_TRUE(subframe_timing.Equals(*updated_subframe_timings().back())); | 795 EXPECT_TRUE(subframe_timing.Equals(*updated_subframe_timings().back())); |
| 806 | 796 |
| 807 CheckNoErrorEvents(); | 797 CheckNoErrorEvents(); |
| 808 } | 798 } |
| 809 | 799 |
| 810 } // namespace page_load_metrics | 800 } // namespace page_load_metrics |
| OLD | NEW |