| OLD | NEW |
| (Empty) |
| 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/android/preferences/important_sites_util.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "base/files/scoped_temp_dir.h" | |
| 11 #include "base/macros.h" | |
| 12 #include "base/metrics/histogram_macros.h" | |
| 13 #include "base/metrics/sample_vector.h" | |
| 14 #include "base/strings/utf_string_conversions.h" | |
| 15 #include "base/test/histogram_tester.h" | |
| 16 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | |
| 17 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | |
| 18 #include "chrome/browser/engagement/site_engagement_score.h" | |
| 19 #include "chrome/browser/engagement/site_engagement_service.h" | |
| 20 #include "chrome/browser/history/history_service_factory.h" | |
| 21 #include "chrome/test/base/chrome_render_view_host_test_harness.h" | |
| 22 #include "chrome/test/base/testing_profile.h" | |
| 23 #include "components/bookmarks/browser/bookmark_model.h" | |
| 24 #include "components/bookmarks/test/bookmark_test_helpers.h" | |
| 25 #include "components/content_settings/core/browser/host_content_settings_map.h" | |
| 26 #include "components/content_settings/core/common/content_settings.h" | |
| 27 #include "components/content_settings/core/common/content_settings_pattern.h" | |
| 28 #include "components/history/core/browser/history_database_params.h" | |
| 29 #include "components/history/core/browser/history_service.h" | |
| 30 #include "components/history/core/test/test_history_database.h" | |
| 31 #include "components/keyed_service/core/keyed_service.h" | |
| 32 #include "content/public/browser/web_contents.h" | |
| 33 #include "testing/gmock/include/gmock/gmock.h" | |
| 34 #include "testing/gtest/include/gtest/gtest.h" | |
| 35 | |
| 36 namespace { | |
| 37 using BookmarkModel = bookmarks::BookmarkModel; | |
| 38 using ImportantDomainInfo = ImportantSitesUtil::ImportantDomainInfo; | |
| 39 | |
| 40 const size_t kNumImportantSites = 5; | |
| 41 base::FilePath g_temp_history_dir; | |
| 42 | |
| 43 std::unique_ptr<KeyedService> BuildTestHistoryService( | |
| 44 content::BrowserContext* context) { | |
| 45 std::unique_ptr<history::HistoryService> service( | |
| 46 new history::HistoryService()); | |
| 47 service->Init(history::TestHistoryDatabaseParamsForPath(g_temp_history_dir)); | |
| 48 return std::move(service); | |
| 49 } | |
| 50 | |
| 51 // We only need to reproduce the values that we are testing. The values here | |
| 52 // need to match the values in important_sites_util. | |
| 53 enum ImportantReasonForTesting { | |
| 54 ENGAGEMENT = 0, | |
| 55 BOOKMARKS = 2, | |
| 56 NOTIFICATIONS = 4 | |
| 57 }; | |
| 58 | |
| 59 // We only need to reproduce the values that we are testing. The values here | |
| 60 // need to match the values in important_sites_util. | |
| 61 enum CrossedReasonForTesting { | |
| 62 CROSSED_NOTIFICATIONS_AND_ENGAGEMENT = 3, | |
| 63 CROSSED_REASON_UNKNOWN = 7, | |
| 64 }; | |
| 65 | |
| 66 } // namespace | |
| 67 | |
| 68 class ImportantSitesUtilTest : public ChromeRenderViewHostTestHarness { | |
| 69 public: | |
| 70 void SetUp() override { | |
| 71 ChromeRenderViewHostTestHarness::SetUp(); | |
| 72 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 73 g_temp_history_dir = temp_dir_.GetPath(); | |
| 74 HistoryServiceFactory::GetInstance()->SetTestingFactory( | |
| 75 profile(), &BuildTestHistoryService); | |
| 76 SiteEngagementScore::SetParamValuesForTesting(); | |
| 77 } | |
| 78 | |
| 79 void AddContentSetting(ContentSettingsType type, | |
| 80 ContentSetting setting, | |
| 81 const GURL& origin) { | |
| 82 HostContentSettingsMapFactory::GetForProfile(profile()) | |
| 83 ->SetContentSettingCustomScope( | |
| 84 ContentSettingsPattern::FromURLNoWildcard(origin), | |
| 85 ContentSettingsPattern::Wildcard(), type, | |
| 86 content_settings::ResourceIdentifier(), setting); | |
| 87 EXPECT_EQ(setting, | |
| 88 HostContentSettingsMapFactory::GetForProfile(profile()) | |
| 89 ->GetContentSetting(origin, GURL(), type, | |
| 90 content_settings::ResourceIdentifier())); | |
| 91 } | |
| 92 | |
| 93 void AddBookmark(const GURL& origin) { | |
| 94 if (!model_) { | |
| 95 profile()->CreateBookmarkModel(true); | |
| 96 model_ = BookmarkModelFactory::GetForBrowserContext(profile()); | |
| 97 bookmarks::test::WaitForBookmarkModelToLoad(model_); | |
| 98 } | |
| 99 | |
| 100 model_->AddURL(model_->bookmark_bar_node(), 0, | |
| 101 base::ASCIIToUTF16(origin.spec()), origin); | |
| 102 } | |
| 103 | |
| 104 void ExpectImportantResultsEq( | |
| 105 const std::vector<std::string>& domains, | |
| 106 const std::vector<GURL>& expected_sorted_origins, | |
| 107 const std::vector<ImportantDomainInfo>& important_sites) { | |
| 108 ASSERT_EQ(domains.size(), important_sites.size()); | |
| 109 ASSERT_EQ(expected_sorted_origins.size(), important_sites.size()); | |
| 110 for (size_t i = 0; i < important_sites.size(); i++) { | |
| 111 EXPECT_EQ(domains[i], important_sites[i].registerable_domain); | |
| 112 EXPECT_EQ(expected_sorted_origins[i], important_sites[i].example_origin); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 private: | |
| 117 base::ScopedTempDir temp_dir_; | |
| 118 BookmarkModel* model_ = nullptr; | |
| 119 }; | |
| 120 | |
| 121 TEST_F(ImportantSitesUtilTest, TestNoImportantSites) { | |
| 122 EXPECT_TRUE(ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 123 profile(), kNumImportantSites) | |
| 124 .empty()); | |
| 125 } | |
| 126 | |
| 127 TEST_F(ImportantSitesUtilTest, SourceOrdering) { | |
| 128 SiteEngagementService* service = SiteEngagementService::Get(profile()); | |
| 129 ASSERT_TRUE(service); | |
| 130 | |
| 131 GURL url1("http://www.google.com/"); | |
| 132 GURL url2("https://www.google.com/"); | |
| 133 GURL url3("https://drive.google.com/"); | |
| 134 GURL url4("https://www.chrome.com/"); | |
| 135 GURL url5("https://www.example.com/"); | |
| 136 GURL url6("https://youtube.com/"); | |
| 137 GURL url7("https://foo.bar/"); | |
| 138 | |
| 139 service->ResetScoreForURL(url1, 5); | |
| 140 service->ResetScoreForURL(url2, 2); // Below medium engagement (5). | |
| 141 service->ResetScoreForURL(url3, 7); | |
| 142 service->ResetScoreForURL(url4, 8); | |
| 143 service->ResetScoreForURL(url5, 9); | |
| 144 service->ResetScoreForURL(url6, 1); // Below the medium engagement (5). | |
| 145 service->ResetScoreForURL(url7, 11); | |
| 146 | |
| 147 // Here we should have: | |
| 148 // 1: removed domains below minimum engagement, | |
| 149 // 2: combined the google.com entries, and | |
| 150 // 3: sorted by the score. | |
| 151 std::vector<ImportantDomainInfo> important_sites = | |
| 152 ImportantSitesUtil::GetImportantRegisterableDomains(profile(), | |
| 153 kNumImportantSites); | |
| 154 std::vector<std::string> expected_sorted_domains = { | |
| 155 "foo.bar", "example.com", "chrome.com", "google.com"}; | |
| 156 std::vector<GURL> expected_sorted_origins = {url7, url5, url4, url3}; | |
| 157 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 158 important_sites); | |
| 159 | |
| 160 // Test that notifications get moved to the front. | |
| 161 AddContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW, | |
| 162 url6); | |
| 163 // BLOCK'ed sites don't count. We want to make sure we only bump sites that | |
| 164 // were granted the permsion. | |
| 165 AddContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_BLOCK, | |
| 166 url1); | |
| 167 | |
| 168 // Same as above, but the site with notifications should be at the front. | |
| 169 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 170 profile(), kNumImportantSites); | |
| 171 expected_sorted_domains = {"youtube.com", "foo.bar", "example.com", | |
| 172 "chrome.com", "google.com"}; | |
| 173 expected_sorted_origins = {url6, url7, url5, url4, url3}; | |
| 174 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 175 important_sites); | |
| 176 | |
| 177 // Test that bookmarks move above engagements and below notifications. | |
| 178 AddBookmark(url1); | |
| 179 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 180 profile(), kNumImportantSites); | |
| 181 expected_sorted_domains = {"youtube.com", "google.com", "foo.bar", | |
| 182 "example.com", "chrome.com"}; | |
| 183 expected_sorted_origins = {url6, url3, url7, url5, url4}; | |
| 184 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 185 important_sites); | |
| 186 } | |
| 187 | |
| 188 TEST_F(ImportantSitesUtilTest, TooManyBookmarks) { | |
| 189 SiteEngagementService* service = SiteEngagementService::Get(profile()); | |
| 190 ASSERT_TRUE(service); | |
| 191 | |
| 192 GURL url1("http://www.google.com/"); | |
| 193 GURL url2("https://www.google.com/"); | |
| 194 GURL url3("https://drive.google.com/"); | |
| 195 GURL url4("https://www.chrome.com/"); | |
| 196 GURL url5("https://www.example.com/"); | |
| 197 GURL url6("https://youtube.com/"); | |
| 198 GURL url7("https://foo.bar/"); | |
| 199 | |
| 200 // Add some as bookmarks. | |
| 201 AddBookmark(url1); | |
| 202 AddBookmark(url2); | |
| 203 AddBookmark(url3); | |
| 204 AddBookmark(url4); | |
| 205 AddBookmark(url5); | |
| 206 | |
| 207 // We have just below our limit, so all sites are important (the first three | |
| 208 // origins collapse, so we end up with 3). | |
| 209 std::vector<ImportantDomainInfo> important_sites = | |
| 210 ImportantSitesUtil::GetImportantRegisterableDomains(profile(), | |
| 211 kNumImportantSites); | |
| 212 EXPECT_EQ(3u, important_sites.size()); | |
| 213 | |
| 214 // Add the rest, which should put us over the limit. | |
| 215 AddBookmark(url6); | |
| 216 AddBookmark(url7); | |
| 217 // Too many bookmarks! Nothing shows up now. | |
| 218 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 219 profile(), kNumImportantSites); | |
| 220 EXPECT_EQ(0u, important_sites.size()); | |
| 221 | |
| 222 // If we add some site engagement, these should show up in order (even though | |
| 223 // the engagement is too low for a signal by itself). | |
| 224 service->ResetScoreForURL(url1, 2); | |
| 225 service->ResetScoreForURL(url4, 3); | |
| 226 service->ResetScoreForURL(url7, 0); | |
| 227 | |
| 228 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 229 profile(), kNumImportantSites); | |
| 230 ASSERT_EQ(2u, important_sites.size()); | |
| 231 std::vector<std::string> expected_sorted_domains = {"google.com", | |
| 232 "chrome.com"}; | |
| 233 std::vector<GURL> expected_sorted_origins = {url1, url4}; | |
| 234 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 235 important_sites); | |
| 236 } | |
| 237 | |
| 238 TEST_F(ImportantSitesUtilTest, Blacklisting) { | |
| 239 SiteEngagementService* service = SiteEngagementService::Get(profile()); | |
| 240 ASSERT_TRUE(service); | |
| 241 | |
| 242 GURL url1("http://www.google.com/"); | |
| 243 | |
| 244 // Set a bunch of positive signals. | |
| 245 service->ResetScoreForURL(url1, 5); | |
| 246 AddBookmark(url1); | |
| 247 AddContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW, | |
| 248 url1); | |
| 249 | |
| 250 // Important fetch 1. | |
| 251 std::vector<ImportantDomainInfo> important_sites = | |
| 252 ImportantSitesUtil::GetImportantRegisterableDomains(profile(), | |
| 253 kNumImportantSites); | |
| 254 std::vector<std::string> expected_sorted_domains = {"google.com"}; | |
| 255 std::vector<GURL> expected_sorted_origins = {url1}; | |
| 256 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 257 important_sites); | |
| 258 ASSERT_EQ(1u, important_sites.size()); | |
| 259 // Record ignore twice. | |
| 260 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 261 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 262 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 263 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 264 | |
| 265 // Important fetch 2. | |
| 266 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 267 profile(), kNumImportantSites); | |
| 268 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 269 important_sites); | |
| 270 // We shouldn't blacklist after first two times. | |
| 271 ASSERT_EQ(1u, important_sites.size()); | |
| 272 | |
| 273 // Record ignore 3rd time. | |
| 274 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 275 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 276 | |
| 277 // Important fetch 3. We should be blacklisted now. | |
| 278 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 279 profile(), kNumImportantSites); | |
| 280 ASSERT_EQ(0u, important_sites.size()); | |
| 281 } | |
| 282 | |
| 283 TEST_F(ImportantSitesUtilTest, BlacklistingReset) { | |
| 284 SiteEngagementService* service = SiteEngagementService::Get(profile()); | |
| 285 ASSERT_TRUE(service); | |
| 286 | |
| 287 GURL url1("http://www.google.com/"); | |
| 288 | |
| 289 // Set a bunch of positive signals. | |
| 290 service->ResetScoreForURL(url1, 5); | |
| 291 AddBookmark(url1); | |
| 292 AddContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW, | |
| 293 url1); | |
| 294 | |
| 295 std::vector<ImportantDomainInfo> important_sites = | |
| 296 ImportantSitesUtil::GetImportantRegisterableDomains(profile(), | |
| 297 kNumImportantSites); | |
| 298 | |
| 299 // Record ignored twice. | |
| 300 ASSERT_EQ(1u, important_sites.size()); | |
| 301 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 302 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 303 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 304 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 305 | |
| 306 // Important fetch, we should still be there. | |
| 307 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 308 profile(), kNumImportantSites); | |
| 309 std::vector<std::string> expected_sorted_domains = {"google.com"}; | |
| 310 std::vector<GURL> expected_sorted_origins = {url1}; | |
| 311 ASSERT_EQ(1u, important_sites.size()); | |
| 312 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 313 important_sites); | |
| 314 | |
| 315 // Record NOT ignored. | |
| 316 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 317 profile(), {"google.com"}, {important_sites[0].reason_bitfield}, {}, {}); | |
| 318 | |
| 319 // Record ignored twice again. | |
| 320 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 321 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 322 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 323 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 324 | |
| 325 // Important fetch, we should still be there. | |
| 326 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 327 profile(), kNumImportantSites); | |
| 328 ExpectImportantResultsEq(expected_sorted_domains, expected_sorted_origins, | |
| 329 important_sites); | |
| 330 | |
| 331 // Record ignored 3rd time in a row. | |
| 332 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 333 profile(), {}, {}, {"google.com"}, {important_sites[0].reason_bitfield}); | |
| 334 | |
| 335 // Blacklisted now. | |
| 336 important_sites = ImportantSitesUtil::GetImportantRegisterableDomains( | |
| 337 profile(), kNumImportantSites); | |
| 338 EXPECT_EQ(0u, important_sites.size()); | |
| 339 } | |
| 340 | |
| 341 TEST_F(ImportantSitesUtilTest, Metrics) { | |
| 342 SiteEngagementService* service = SiteEngagementService::Get(profile()); | |
| 343 ASSERT_TRUE(service); | |
| 344 base::HistogramTester histogram_tester; | |
| 345 | |
| 346 GURL url1("http://www.google.com/"); | |
| 347 service->ResetScoreForURL(url1, 5); | |
| 348 AddContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW, | |
| 349 url1); | |
| 350 | |
| 351 GURL url2("http://www.youtube.com/"); | |
| 352 AddBookmark(url2); | |
| 353 | |
| 354 GURL url3("http://www.bad.com/"); | |
| 355 AddBookmark(url3); | |
| 356 | |
| 357 std::vector<ImportantDomainInfo> important_sites = | |
| 358 ImportantSitesUtil::GetImportantRegisterableDomains(profile(), | |
| 359 kNumImportantSites); | |
| 360 | |
| 361 ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites( | |
| 362 profile(), {"google.com", "youtube.com"}, | |
| 363 {important_sites[0].reason_bitfield, important_sites[1].reason_bitfield}, | |
| 364 {"bad.com"}, {important_sites[2].reason_bitfield}); | |
| 365 | |
| 366 EXPECT_THAT(histogram_tester.GetAllSamples( | |
| 367 "Storage.ImportantSites.CBDChosenReason"), | |
| 368 testing::ElementsAre( | |
| 369 base::Bucket(ENGAGEMENT, 1), | |
| 370 base::Bucket(BOOKMARKS, 1), | |
| 371 base::Bucket(NOTIFICATIONS, 1))); | |
| 372 | |
| 373 EXPECT_THAT( | |
| 374 histogram_tester.GetAllSamples("Storage.ImportantSites.CBDIgnoredReason"), | |
| 375 testing::ElementsAre(base::Bucket(BOOKMARKS, 1))); | |
| 376 | |
| 377 // Bookmarks are "unknown", as they were added after the crossed reasons. | |
| 378 EXPECT_THAT(histogram_tester.GetAllSamples( | |
| 379 "Storage.BlacklistedImportantSites.Reason"), | |
| 380 testing::ElementsAre( | |
| 381 base::Bucket(CROSSED_NOTIFICATIONS_AND_ENGAGEMENT, 1), | |
| 382 base::Bucket(CROSSED_REASON_UNKNOWN, 1))); | |
| 383 } | |
| OLD | NEW |