OLD | NEW |
(Empty) | |
| 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 "chrome/browser/predictors/loading_predictor.h" |
| 6 |
| 7 #include <memory> |
| 8 #include <set> |
| 9 #include <string> |
| 10 |
| 11 #include "base/run_loop.h" |
| 12 #include "base/test/histogram_tester.h" |
| 13 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h" |
| 14 #include "chrome/test/base/testing_profile.h" |
| 15 #include "content/public/test/test_browser_thread_bundle.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 namespace predictors { |
| 20 |
| 21 namespace { |
| 22 // First two are prefetchable, last one is not (see SetUp()). |
| 23 const char kUrl[] = "http://www.google.com/cats"; |
| 24 const char kUrl2[] = "http://www.google.com/dogs"; |
| 25 const char kUrl3[] = "https://unknown.website/catsanddogs"; |
| 26 } |
| 27 |
| 28 // Does nothing, controls which URLs are prefetchable. |
| 29 class MockResourcePrefetcherPredictor : public ResourcePrefetchPredictor { |
| 30 public: |
| 31 MockResourcePrefetcherPredictor(const LoadingPredictorConfig& config, |
| 32 Profile* profile) |
| 33 : ResourcePrefetchPredictor(config, profile) {} |
| 34 |
| 35 bool IsUrlPrefetchable(const GURL& main_frame_url) const override { |
| 36 return prefetchable_urls_.find(main_frame_url) != prefetchable_urls_.end(); |
| 37 } |
| 38 |
| 39 void AddPrefetchableUrl(const GURL& url) { prefetchable_urls_.insert(url); } |
| 40 |
| 41 MOCK_METHOD0(StartInitialization, void()); |
| 42 MOCK_METHOD0(Shutdown, void()); |
| 43 MOCK_METHOD1(StartPrefetching, void(const GURL&)); |
| 44 MOCK_METHOD1(StopPrefeching, void(const GURL&)); |
| 45 |
| 46 private: |
| 47 std::set<GURL> prefetchable_urls_; |
| 48 }; |
| 49 |
| 50 class LoadingPredictorTest : public testing::Test { |
| 51 public: |
| 52 LoadingPredictorTest(); |
| 53 ~LoadingPredictorTest() override; |
| 54 void SetUp() override; |
| 55 void TearDown() override; |
| 56 |
| 57 protected: |
| 58 content::TestBrowserThreadBundle thread_bundle_; |
| 59 std::unique_ptr<LoadingPredictor> predictor_; |
| 60 std::unique_ptr<TestingProfile> profile_; |
| 61 }; |
| 62 |
| 63 LoadingPredictorTest::LoadingPredictorTest() |
| 64 : profile_(base::MakeUnique<TestingProfile>()) {} |
| 65 |
| 66 LoadingPredictorTest::~LoadingPredictorTest() { |
| 67 profile_ = nullptr; |
| 68 base::RunLoop().RunUntilIdle(); |
| 69 } |
| 70 |
| 71 void LoadingPredictorTest::SetUp() { |
| 72 LoadingPredictorConfig config; |
| 73 PopulateTestConfig(&config); |
| 74 predictor_ = base::MakeUnique<LoadingPredictor>(config, profile_.get()); |
| 75 auto mock = |
| 76 base::MakeUnique<MockResourcePrefetcherPredictor>(config, profile_.get()); |
| 77 mock->AddPrefetchableUrl(GURL(kUrl)); |
| 78 mock->AddPrefetchableUrl(GURL(kUrl2)); |
| 79 predictor_->set_mock_resource_prefetch_predictor(std::move(mock)); |
| 80 predictor_->StartInitialization(); |
| 81 base::RunLoop().RunUntilIdle(); |
| 82 } |
| 83 |
| 84 void LoadingPredictorTest::TearDown() { |
| 85 predictor_ = nullptr; |
| 86 profile_->DestroyHistoryService(); |
| 87 } |
| 88 |
| 89 TEST_F(LoadingPredictorTest, TestPrefetchingDurationHistogram) { |
| 90 base::HistogramTester histogram_tester; |
| 91 |
| 92 const GURL url = GURL(kUrl); |
| 93 const GURL url2 = GURL(kUrl2); |
| 94 const GURL url3 = GURL(kUrl3); |
| 95 predictor_->PrepareForPageLoad(url, HintOrigin::EXTERNAL); |
| 96 predictor_->CancelPageLoadHint(url); |
| 97 histogram_tester.ExpectTotalCount( |
| 98 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 1); |
| 99 |
| 100 // Mismatched start / end. |
| 101 predictor_->PrepareForPageLoad(url, HintOrigin::EXTERNAL); |
| 102 predictor_->CancelPageLoadHint(url2); |
| 103 // No increment. |
| 104 histogram_tester.ExpectTotalCount( |
| 105 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 1); |
| 106 |
| 107 // Can track a navigation (url2) while one is still in progress (url). |
| 108 predictor_->PrepareForPageLoad(url2, HintOrigin::EXTERNAL); |
| 109 predictor_->CancelPageLoadHint(url2); |
| 110 histogram_tester.ExpectTotalCount( |
| 111 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 2); |
| 112 |
| 113 // Do not track non-prefetchable URLs. |
| 114 predictor_->PrepareForPageLoad(url3, HintOrigin::EXTERNAL); |
| 115 predictor_->CancelPageLoadHint(url3); |
| 116 // No increment. |
| 117 histogram_tester.ExpectTotalCount( |
| 118 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 2); |
| 119 } |
| 120 |
| 121 TEST_F(LoadingPredictorTest, TestMainFrameResponseCancelsHint) { |
| 122 const GURL url = GURL(kUrl); |
| 123 predictor_->PrepareForPageLoad(url, HintOrigin::EXTERNAL); |
| 124 EXPECT_EQ(1UL, predictor_->active_hints_.size()); |
| 125 |
| 126 auto summary = CreateURLRequestSummary(12, url.spec()); |
| 127 predictor_->OnMainFrameResponse(summary); |
| 128 EXPECT_TRUE(predictor_->active_hints_.empty()); |
| 129 } |
| 130 |
| 131 TEST_F(LoadingPredictorTest, TestMainFrameRequestCancelsStaleNavigations) { |
| 132 const std::string url = kUrl; |
| 133 const std::string url2 = kUrl2; |
| 134 const int tab_id = 12; |
| 135 const auto& active_navigations = predictor_->active_navigations_; |
| 136 const auto& active_hints = predictor_->active_hints_; |
| 137 |
| 138 auto summary = CreateURLRequestSummary(tab_id, url); |
| 139 auto navigation_id = CreateNavigationID(tab_id, url); |
| 140 |
| 141 predictor_->OnMainFrameRequest(summary); |
| 142 EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end()); |
| 143 EXPECT_NE(active_hints.find(GURL(url)), active_hints.end()); |
| 144 |
| 145 summary = CreateURLRequestSummary(tab_id, url2); |
| 146 predictor_->OnMainFrameRequest(summary); |
| 147 EXPECT_EQ(active_navigations.find(navigation_id), active_navigations.end()); |
| 148 EXPECT_EQ(active_hints.find(GURL(url)), active_hints.end()); |
| 149 |
| 150 auto navigation_id2 = CreateNavigationID(tab_id, url2); |
| 151 EXPECT_NE(active_navigations.find(navigation_id2), active_navigations.end()); |
| 152 } |
| 153 |
| 154 TEST_F(LoadingPredictorTest, TestMainFrameResponseClearsNavigations) { |
| 155 const std::string url = kUrl; |
| 156 const std::string redirected = kUrl2; |
| 157 const int tab_id = 12; |
| 158 const auto& active_navigations = predictor_->active_navigations_; |
| 159 const auto& active_hints = predictor_->active_hints_; |
| 160 |
| 161 auto summary = CreateURLRequestSummary(tab_id, url); |
| 162 auto navigation_id = CreateNavigationID(tab_id, url); |
| 163 |
| 164 predictor_->OnMainFrameRequest(summary); |
| 165 EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end()); |
| 166 EXPECT_FALSE(active_hints.empty()); |
| 167 |
| 168 predictor_->OnMainFrameResponse(summary); |
| 169 EXPECT_TRUE(active_navigations.empty()); |
| 170 EXPECT_TRUE(active_hints.empty()); |
| 171 |
| 172 // With redirects. |
| 173 predictor_->OnMainFrameRequest(summary); |
| 174 EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end()); |
| 175 EXPECT_FALSE(active_hints.empty()); |
| 176 |
| 177 summary.redirect_url = GURL(redirected); |
| 178 predictor_->OnMainFrameRedirect(summary); |
| 179 EXPECT_FALSE(active_navigations.empty()); |
| 180 EXPECT_FALSE(active_hints.empty()); |
| 181 |
| 182 summary.navigation_id.main_frame_url = GURL(redirected); |
| 183 predictor_->OnMainFrameResponse(summary); |
| 184 EXPECT_TRUE(active_navigations.empty()); |
| 185 EXPECT_TRUE(active_hints.empty()); |
| 186 } |
| 187 |
| 188 TEST_F(LoadingPredictorTest, TestMainFrameRequestDoesntCancelExternalHint) { |
| 189 const GURL url = GURL(kUrl); |
| 190 const int tab_id = 12; |
| 191 const auto& active_navigations = predictor_->active_navigations_; |
| 192 auto& active_hints = predictor_->active_hints_; |
| 193 |
| 194 predictor_->PrepareForPageLoad(url, HintOrigin::EXTERNAL); |
| 195 auto it = active_hints.find(url); |
| 196 EXPECT_NE(it, active_hints.end()); |
| 197 EXPECT_TRUE(active_navigations.empty()); |
| 198 |
| 199 // To check that the hint is not replaced, set the start time in the past, |
| 200 // and check later that it didn't change. |
| 201 base::TimeTicks start_time = it->second - base::TimeDelta::FromSeconds(10); |
| 202 it->second = start_time; |
| 203 |
| 204 auto summary = CreateURLRequestSummary(tab_id, url.spec()); |
| 205 predictor_->OnMainFrameRequest(summary); |
| 206 EXPECT_NE(active_navigations.find(summary.navigation_id), |
| 207 active_navigations.end()); |
| 208 it = active_hints.find(url); |
| 209 EXPECT_NE(it, active_hints.end()); |
| 210 EXPECT_EQ(start_time, it->second); |
| 211 } |
| 212 |
| 213 TEST_F(LoadingPredictorTest, TestDontTrackNonPrefetchableUrls) { |
| 214 const GURL url3 = GURL(kUrl3); |
| 215 predictor_->PrepareForPageLoad(url3, HintOrigin::EXTERNAL); |
| 216 EXPECT_TRUE(predictor_->active_hints_.empty()); |
| 217 } |
| 218 |
| 219 } // namespace predictors |
OLD | NEW |