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 |