| 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/engagement/site_engagement_service.h" | 5 #include "chrome/browser/engagement/site_engagement_service.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 13 #include "base/test/histogram_tester.h" | 13 #include "base/test/histogram_tester.h" |
| 14 #include "base/test/simple_test_clock.h" | 14 #include "base/test/simple_test_clock.h" |
| 15 #include "base/values.h" | 15 #include "base/values.h" |
| 16 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 16 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 17 #include "chrome/browser/engagement/site_engagement_helper.h" | 17 #include "chrome/browser/engagement/site_engagement_helper.h" |
| 18 #include "chrome/browser/engagement/site_engagement_metrics.h" | 18 #include "chrome/browser/engagement/site_engagement_metrics.h" |
| 19 #include "chrome/browser/engagement/site_engagement_service_factory.h" | 19 #include "chrome/browser/engagement/site_engagement_score.h" |
| 20 #include "chrome/browser/history/history_service_factory.h" | 20 #include "chrome/browser/history/history_service_factory.h" |
| 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 22 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
| 23 #include "chrome/test/base/chrome_render_view_host_test_harness.h" | 23 #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| 24 #include "chrome/test/base/testing_profile.h" | 24 #include "chrome/test/base/testing_profile.h" |
| 25 #include "components/content_settings/core/browser/content_settings_observer.h" | 25 #include "components/content_settings/core/browser/content_settings_observer.h" |
| 26 #include "components/content_settings/core/browser/host_content_settings_map.h" | 26 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 27 #include "components/history/core/browser/history_database_params.h" | 27 #include "components/history/core/browser/history_database_params.h" |
| 28 #include "components/history/core/browser/history_service.h" | 28 #include "components/history/core/browser/history_service.h" |
| 29 #include "components/history/core/test/test_history_database.h" | 29 #include "components/history/core/test/test_history_database.h" |
| 30 #include "content/public/browser/navigation_entry.h" | 30 #include "content/public/browser/navigation_entry.h" |
| 31 #include "content/public/browser/page_navigator.h" | 31 #include "content/public/browser/page_navigator.h" |
| 32 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
| 33 #include "content/public/test/web_contents_tester.h" | 33 #include "content/public/test/web_contents_tester.h" |
| 34 #include "testing/gtest/include/gtest/gtest.h" | 34 #include "testing/gtest/include/gtest/gtest.h" |
| 35 | 35 |
| 36 namespace { | 36 namespace { |
| 37 | 37 |
| 38 base::FilePath g_temp_history_dir; | 38 base::FilePath g_temp_history_dir; |
| 39 | 39 |
| 40 const int kLessAccumulationsThanNeededToMaxDailyEngagement = 2; | |
| 41 const int kMoreAccumulationsThanNeededToMaxDailyEngagement = 40; | 40 const int kMoreAccumulationsThanNeededToMaxDailyEngagement = 40; |
| 42 const int kMoreAccumulationsThanNeededToMaxTotalEngagement = 200; | |
| 43 const int kLessDaysThanNeededToMaxTotalEngagement = 4; | |
| 44 const int kMoreDaysThanNeededToMaxTotalEngagement = 40; | 41 const int kMoreDaysThanNeededToMaxTotalEngagement = 40; |
| 45 const int kLessPeriodsThanNeededToDecayMaxScore = 2; | 42 const int kLessPeriodsThanNeededToDecayMaxScore = 2; |
| 46 const int kMorePeriodsThanNeededToDecayMaxScore = 40; | 43 const int kMorePeriodsThanNeededToDecayMaxScore = 40; |
| 47 | 44 |
| 48 // Waits until a change is observed in site engagement content settings. | 45 // Waits until a change is observed in site engagement content settings. |
| 49 class SiteEngagementChangeWaiter : public content_settings::Observer { | 46 class SiteEngagementChangeWaiter : public content_settings::Observer { |
| 50 public: | 47 public: |
| 51 explicit SiteEngagementChangeWaiter(Profile* profile) : profile_(profile) { | 48 explicit SiteEngagementChangeWaiter(Profile* profile) : profile_(profile) { |
| 52 HostContentSettingsMapFactory::GetForProfile(profile)->AddObserver(this); | 49 HostContentSettingsMapFactory::GetForProfile(profile)->AddObserver(this); |
| 53 } | 50 } |
| 54 ~SiteEngagementChangeWaiter() override { | 51 ~SiteEngagementChangeWaiter() override { |
| 55 HostContentSettingsMapFactory::GetForProfile(profile_) | 52 HostContentSettingsMapFactory::GetForProfile(profile_)->RemoveObserver( |
| 56 ->RemoveObserver(this); | 53 this); |
| 57 } | 54 } |
| 58 | 55 |
| 59 // Overridden from content_settings::Observer: | 56 // Overridden from content_settings::Observer: |
| 60 void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern, | 57 void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern, |
| 61 const ContentSettingsPattern& secondary_pattern, | 58 const ContentSettingsPattern& secondary_pattern, |
| 62 ContentSettingsType content_type, | 59 ContentSettingsType content_type, |
| 63 std::string resource_identifier) override { | 60 std::string resource_identifier) override { |
| 64 if (content_type == CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT) | 61 if (content_type == CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT) |
| 65 Proceed(); | 62 Proceed(); |
| 66 } | 63 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 93 std::unique_ptr<KeyedService> BuildTestHistoryService( | 90 std::unique_ptr<KeyedService> BuildTestHistoryService( |
| 94 content::BrowserContext* context) { | 91 content::BrowserContext* context) { |
| 95 std::unique_ptr<history::HistoryService> service( | 92 std::unique_ptr<history::HistoryService> service( |
| 96 new history::HistoryService()); | 93 new history::HistoryService()); |
| 97 service->Init(history::TestHistoryDatabaseParamsForPath(g_temp_history_dir)); | 94 service->Init(history::TestHistoryDatabaseParamsForPath(g_temp_history_dir)); |
| 98 return std::move(service); | 95 return std::move(service); |
| 99 } | 96 } |
| 100 | 97 |
| 101 } // namespace | 98 } // namespace |
| 102 | 99 |
| 103 class SiteEngagementScoreTest : public testing::Test { | |
| 104 public: | |
| 105 SiteEngagementScoreTest() : score_(&test_clock_) {} | |
| 106 | |
| 107 void SetUp() override { | |
| 108 testing::Test::SetUp(); | |
| 109 // Disable the first engagement bonus for tests. | |
| 110 SiteEngagementScore::SetParamValuesForTesting(); | |
| 111 } | |
| 112 | |
| 113 protected: | |
| 114 void VerifyScore(const SiteEngagementScore& score, | |
| 115 double expected_raw_score, | |
| 116 double expected_points_added_today, | |
| 117 base::Time expected_last_engagement_time) { | |
| 118 EXPECT_EQ(expected_raw_score, score.raw_score_); | |
| 119 EXPECT_EQ(expected_points_added_today, score.points_added_today_); | |
| 120 EXPECT_EQ(expected_last_engagement_time, score.last_engagement_time_); | |
| 121 } | |
| 122 | |
| 123 void UpdateScore(SiteEngagementScore* score, | |
| 124 double raw_score, | |
| 125 double points_added_today, | |
| 126 base::Time last_engagement_time) { | |
| 127 score->raw_score_ = raw_score; | |
| 128 score->points_added_today_ = points_added_today; | |
| 129 score->last_engagement_time_ = last_engagement_time; | |
| 130 } | |
| 131 | |
| 132 void TestScoreInitializesAndUpdates( | |
| 133 base::DictionaryValue* score_dict, | |
| 134 double expected_raw_score, | |
| 135 double expected_points_added_today, | |
| 136 base::Time expected_last_engagement_time) { | |
| 137 SiteEngagementScore initial_score(&test_clock_, *score_dict); | |
| 138 VerifyScore(initial_score, expected_raw_score, expected_points_added_today, | |
| 139 expected_last_engagement_time); | |
| 140 | |
| 141 // Updating the score dict should return false, as the score shouldn't | |
| 142 // have changed at this point. | |
| 143 EXPECT_FALSE(initial_score.UpdateScoreDict(score_dict)); | |
| 144 | |
| 145 // Update the score to new values and verify it updates the score dict | |
| 146 // correctly. | |
| 147 base::Time different_day = | |
| 148 GetReferenceTime() + base::TimeDelta::FromDays(1); | |
| 149 UpdateScore(&initial_score, 5, 10, different_day); | |
| 150 EXPECT_TRUE(initial_score.UpdateScoreDict(score_dict)); | |
| 151 SiteEngagementScore updated_score(&test_clock_, *score_dict); | |
| 152 VerifyScore(updated_score, 5, 10, different_day); | |
| 153 } | |
| 154 | |
| 155 void SetFirstDailyEngagementPointsForTesting(double points) { | |
| 156 SiteEngagementScore::param_values | |
| 157 [SiteEngagementScore::FIRST_DAILY_ENGAGEMENT] = points; | |
| 158 } | |
| 159 | |
| 160 base::SimpleTestClock test_clock_; | |
| 161 SiteEngagementScore score_; | |
| 162 }; | |
| 163 | |
| 164 // Accumulate score many times on the same day. Ensure each time the score goes | |
| 165 // up, but not more than the maximum per day. | |
| 166 TEST_F(SiteEngagementScoreTest, AccumulateOnSameDay) { | |
| 167 base::Time reference_time = GetReferenceTime(); | |
| 168 | |
| 169 test_clock_.SetNow(reference_time); | |
| 170 for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { | |
| 171 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 172 EXPECT_EQ(std::min(SiteEngagementScore::GetMaxPointsPerDay(), | |
| 173 (i + 1) * SiteEngagementScore::GetNavigationPoints()), | |
| 174 score_.Score()); | |
| 175 } | |
| 176 | |
| 177 EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.Score()); | |
| 178 } | |
| 179 | |
| 180 // Accumulate on the first day to max that day's engagement, then accumulate on | |
| 181 // a different day. | |
| 182 TEST_F(SiteEngagementScoreTest, AccumulateOnTwoDays) { | |
| 183 base::Time reference_time = GetReferenceTime(); | |
| 184 base::Time later_date = reference_time + base::TimeDelta::FromDays(2); | |
| 185 | |
| 186 test_clock_.SetNow(reference_time); | |
| 187 for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) | |
| 188 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 189 | |
| 190 EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.Score()); | |
| 191 | |
| 192 test_clock_.SetNow(later_date); | |
| 193 for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { | |
| 194 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 195 double day_score = | |
| 196 std::min(SiteEngagementScore::GetMaxPointsPerDay(), | |
| 197 (i + 1) * SiteEngagementScore::GetNavigationPoints()); | |
| 198 EXPECT_EQ(day_score + SiteEngagementScore::GetMaxPointsPerDay(), | |
| 199 score_.Score()); | |
| 200 } | |
| 201 | |
| 202 EXPECT_EQ(2 * SiteEngagementScore::GetMaxPointsPerDay(), score_.Score()); | |
| 203 } | |
| 204 | |
| 205 // Accumulate score on many consecutive days and ensure the score doesn't exceed | |
| 206 // the maximum allowed. | |
| 207 TEST_F(SiteEngagementScoreTest, AccumulateALotOnManyDays) { | |
| 208 base::Time current_day = GetReferenceTime(); | |
| 209 | |
| 210 for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) { | |
| 211 current_day += base::TimeDelta::FromDays(1); | |
| 212 test_clock_.SetNow(current_day); | |
| 213 for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) | |
| 214 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 215 | |
| 216 EXPECT_EQ(std::min(SiteEngagementScore::kMaxPoints, | |
| 217 (i + 1) * SiteEngagementScore::GetMaxPointsPerDay()), | |
| 218 score_.Score()); | |
| 219 } | |
| 220 | |
| 221 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score()); | |
| 222 } | |
| 223 | |
| 224 // Accumulate a little on many consecutive days and ensure the score doesn't | |
| 225 // exceed the maximum allowed. | |
| 226 TEST_F(SiteEngagementScoreTest, AccumulateALittleOnManyDays) { | |
| 227 base::Time current_day = GetReferenceTime(); | |
| 228 | |
| 229 for (int i = 0; i < kMoreAccumulationsThanNeededToMaxTotalEngagement; ++i) { | |
| 230 current_day += base::TimeDelta::FromDays(1); | |
| 231 test_clock_.SetNow(current_day); | |
| 232 | |
| 233 for (int j = 0; j < kLessAccumulationsThanNeededToMaxDailyEngagement; ++j) | |
| 234 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 235 | |
| 236 EXPECT_EQ( | |
| 237 std::min(SiteEngagementScore::kMaxPoints, | |
| 238 (i + 1) * kLessAccumulationsThanNeededToMaxDailyEngagement * | |
| 239 SiteEngagementScore::GetNavigationPoints()), | |
| 240 score_.Score()); | |
| 241 } | |
| 242 | |
| 243 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score()); | |
| 244 } | |
| 245 | |
| 246 // Accumulate a bit, then check the score decays properly for a range of times. | |
| 247 TEST_F(SiteEngagementScoreTest, ScoresDecayOverTime) { | |
| 248 base::Time current_day = GetReferenceTime(); | |
| 249 | |
| 250 // First max the score. | |
| 251 for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) { | |
| 252 current_day += base::TimeDelta::FromDays(1); | |
| 253 test_clock_.SetNow(current_day); | |
| 254 | |
| 255 for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) | |
| 256 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 257 } | |
| 258 | |
| 259 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score()); | |
| 260 | |
| 261 // The score should not have decayed before the first decay period has | |
| 262 // elapsed. | |
| 263 test_clock_.SetNow(current_day + | |
| 264 base::TimeDelta::FromDays( | |
| 265 SiteEngagementScore::GetDecayPeriodInDays() - 1)); | |
| 266 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score()); | |
| 267 | |
| 268 // The score should have decayed by one chunk after one decay period has | |
| 269 // elapsed. | |
| 270 test_clock_.SetNow( | |
| 271 current_day + | |
| 272 base::TimeDelta::FromDays(SiteEngagementScore::GetDecayPeriodInDays())); | |
| 273 EXPECT_EQ( | |
| 274 SiteEngagementScore::kMaxPoints - SiteEngagementScore::GetDecayPoints(), | |
| 275 score_.Score()); | |
| 276 | |
| 277 // The score should have decayed by the right number of chunks after a few | |
| 278 // decay periods have elapsed. | |
| 279 test_clock_.SetNow( | |
| 280 current_day + | |
| 281 base::TimeDelta::FromDays(kLessPeriodsThanNeededToDecayMaxScore * | |
| 282 SiteEngagementScore::GetDecayPeriodInDays())); | |
| 283 EXPECT_EQ(SiteEngagementScore::kMaxPoints - | |
| 284 kLessPeriodsThanNeededToDecayMaxScore * | |
| 285 SiteEngagementScore::GetDecayPoints(), | |
| 286 score_.Score()); | |
| 287 | |
| 288 // The score should not decay below zero. | |
| 289 test_clock_.SetNow( | |
| 290 current_day + | |
| 291 base::TimeDelta::FromDays(kMorePeriodsThanNeededToDecayMaxScore * | |
| 292 SiteEngagementScore::GetDecayPeriodInDays())); | |
| 293 EXPECT_EQ(0, score_.Score()); | |
| 294 } | |
| 295 | |
| 296 // Test that any expected decays are applied before adding points. | |
| 297 TEST_F(SiteEngagementScoreTest, DecaysAppliedBeforeAdd) { | |
| 298 base::Time current_day = GetReferenceTime(); | |
| 299 | |
| 300 // Get the score up to something that can handle a bit of decay before | |
| 301 for (int i = 0; i < kLessDaysThanNeededToMaxTotalEngagement; ++i) { | |
| 302 current_day += base::TimeDelta::FromDays(1); | |
| 303 test_clock_.SetNow(current_day); | |
| 304 | |
| 305 for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) | |
| 306 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 307 } | |
| 308 | |
| 309 double initial_score = kLessDaysThanNeededToMaxTotalEngagement * | |
| 310 SiteEngagementScore::GetMaxPointsPerDay(); | |
| 311 EXPECT_EQ(initial_score, score_.Score()); | |
| 312 | |
| 313 // Go forward a few decay periods. | |
| 314 test_clock_.SetNow( | |
| 315 current_day + | |
| 316 base::TimeDelta::FromDays(kLessPeriodsThanNeededToDecayMaxScore * | |
| 317 SiteEngagementScore::GetDecayPeriodInDays())); | |
| 318 | |
| 319 double decayed_score = initial_score - | |
| 320 kLessPeriodsThanNeededToDecayMaxScore * | |
| 321 SiteEngagementScore::GetDecayPoints(); | |
| 322 EXPECT_EQ(decayed_score, score_.Score()); | |
| 323 | |
| 324 // Now add some points. | |
| 325 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 326 EXPECT_EQ(decayed_score + SiteEngagementScore::GetNavigationPoints(), | |
| 327 score_.Score()); | |
| 328 } | |
| 329 | |
| 330 // Test that going back in time is handled properly. | |
| 331 TEST_F(SiteEngagementScoreTest, GoBackInTime) { | |
| 332 base::Time current_day = GetReferenceTime(); | |
| 333 | |
| 334 test_clock_.SetNow(current_day); | |
| 335 for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) | |
| 336 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 337 | |
| 338 EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.Score()); | |
| 339 | |
| 340 // Adding to the score on an earlier date should be treated like another day, | |
| 341 // and should not cause any decay. | |
| 342 test_clock_.SetNow(current_day - base::TimeDelta::FromDays( | |
| 343 kMorePeriodsThanNeededToDecayMaxScore * | |
| 344 SiteEngagementScore::GetDecayPoints())); | |
| 345 for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { | |
| 346 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 347 double day_score = | |
| 348 std::min(SiteEngagementScore::GetMaxPointsPerDay(), | |
| 349 (i + 1) * SiteEngagementScore::GetNavigationPoints()); | |
| 350 EXPECT_EQ(day_score + SiteEngagementScore::GetMaxPointsPerDay(), | |
| 351 score_.Score()); | |
| 352 } | |
| 353 | |
| 354 EXPECT_EQ(2 * SiteEngagementScore::GetMaxPointsPerDay(), score_.Score()); | |
| 355 } | |
| 356 | |
| 357 // Test that scores are read / written correctly from / to empty score | |
| 358 // dictionaries. | |
| 359 TEST_F(SiteEngagementScoreTest, EmptyDictionary) { | |
| 360 base::DictionaryValue dict; | |
| 361 TestScoreInitializesAndUpdates(&dict, 0, 0, base::Time()); | |
| 362 } | |
| 363 | |
| 364 // Test that scores are read / written correctly from / to partially empty | |
| 365 // score dictionaries. | |
| 366 TEST_F(SiteEngagementScoreTest, PartiallyEmptyDictionary) { | |
| 367 base::DictionaryValue dict; | |
| 368 dict.SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2); | |
| 369 | |
| 370 TestScoreInitializesAndUpdates(&dict, 0, 2, base::Time()); | |
| 371 } | |
| 372 | |
| 373 // Test that scores are read / written correctly from / to populated score | |
| 374 // dictionaries. | |
| 375 TEST_F(SiteEngagementScoreTest, PopulatedDictionary) { | |
| 376 base::DictionaryValue dict; | |
| 377 dict.SetDouble(SiteEngagementScore::kRawScoreKey, 1); | |
| 378 dict.SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2); | |
| 379 dict.SetDouble(SiteEngagementScore::kLastEngagementTimeKey, | |
| 380 GetReferenceTime().ToInternalValue()); | |
| 381 | |
| 382 TestScoreInitializesAndUpdates(&dict, 1, 2, GetReferenceTime()); | |
| 383 } | |
| 384 | |
| 385 // Ensure bonus engagement is awarded for the first engagement of a day. | |
| 386 TEST_F(SiteEngagementScoreTest, FirstDailyEngagementBonus) { | |
| 387 SetFirstDailyEngagementPointsForTesting(0.5); | |
| 388 | |
| 389 SiteEngagementScore score1(&test_clock_); | |
| 390 SiteEngagementScore score2(&test_clock_); | |
| 391 base::Time current_day = GetReferenceTime(); | |
| 392 | |
| 393 test_clock_.SetNow(current_day); | |
| 394 | |
| 395 // The first engagement event gets the bonus. | |
| 396 score1.AddPoints(0.5); | |
| 397 EXPECT_EQ(1.0, score1.Score()); | |
| 398 | |
| 399 // Subsequent events do not. | |
| 400 score1.AddPoints(0.5); | |
| 401 EXPECT_EQ(1.5, score1.Score()); | |
| 402 | |
| 403 // Bonuses are awarded independently between scores. | |
| 404 score2.AddPoints(1.0); | |
| 405 EXPECT_EQ(1.5, score2.Score()); | |
| 406 score2.AddPoints(1.0); | |
| 407 EXPECT_EQ(2.5, score2.Score()); | |
| 408 | |
| 409 test_clock_.SetNow(current_day + base::TimeDelta::FromDays(1)); | |
| 410 | |
| 411 // The first event for the next day gets the bonus. | |
| 412 score1.AddPoints(0.5); | |
| 413 EXPECT_EQ(2.5, score1.Score()); | |
| 414 | |
| 415 // Subsequent events do not. | |
| 416 score1.AddPoints(0.5); | |
| 417 EXPECT_EQ(3.0, score1.Score()); | |
| 418 | |
| 419 score2.AddPoints(1.0); | |
| 420 EXPECT_EQ(4.0, score2.Score()); | |
| 421 score2.AddPoints(1.0); | |
| 422 EXPECT_EQ(5.0, score2.Score()); | |
| 423 } | |
| 424 | |
| 425 // Test that resetting a score has the correct properties. | |
| 426 TEST_F(SiteEngagementScoreTest, Reset) { | |
| 427 base::Time current_day = GetReferenceTime(); | |
| 428 | |
| 429 test_clock_.SetNow(current_day); | |
| 430 score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); | |
| 431 EXPECT_EQ(SiteEngagementScore::GetNavigationPoints(), score_.Score()); | |
| 432 | |
| 433 current_day += base::TimeDelta::FromDays(7); | |
| 434 test_clock_.SetNow(current_day); | |
| 435 | |
| 436 score_.Reset(20.0, nullptr); | |
| 437 EXPECT_DOUBLE_EQ(20.0, score_.Score()); | |
| 438 EXPECT_DOUBLE_EQ(0, score_.points_added_today_); | |
| 439 EXPECT_EQ(current_day, score_.last_engagement_time_); | |
| 440 EXPECT_TRUE(score_.last_shortcut_launch_time_.is_null()); | |
| 441 | |
| 442 // Adding points after the reset should work as normal. | |
| 443 score_.AddPoints(5); | |
| 444 EXPECT_EQ(25.0, score_.Score()); | |
| 445 | |
| 446 // The decay should happen one decay period from the current time. | |
| 447 test_clock_.SetNow(current_day + | |
| 448 base::TimeDelta::FromDays( | |
| 449 SiteEngagementScore::GetDecayPeriodInDays() + 1)); | |
| 450 EXPECT_EQ(25.0 - SiteEngagementScore::GetDecayPoints(), score_.Score()); | |
| 451 | |
| 452 // Ensure that manually setting a time works as expected. | |
| 453 score_.AddPoints(5); | |
| 454 test_clock_.SetNow(GetReferenceTime()); | |
| 455 base::Time now = test_clock_.Now(); | |
| 456 score_.Reset(10.0, &now); | |
| 457 | |
| 458 EXPECT_DOUBLE_EQ(10.0, score_.Score()); | |
| 459 EXPECT_DOUBLE_EQ(0, score_.points_added_today_); | |
| 460 EXPECT_EQ(now, score_.last_engagement_time_); | |
| 461 EXPECT_TRUE(score_.last_shortcut_launch_time_.is_null()); | |
| 462 | |
| 463 score_.set_last_shortcut_launch_time(test_clock_.Now()); | |
| 464 test_clock_.SetNow(GetReferenceTime() + base::TimeDelta::FromDays(3)); | |
| 465 now = test_clock_.Now(); | |
| 466 score_.Reset(15.0, &now); | |
| 467 | |
| 468 // 5 bonus from the last shortcut launch. | |
| 469 EXPECT_DOUBLE_EQ(20.0, score_.Score()); | |
| 470 EXPECT_DOUBLE_EQ(0, score_.points_added_today_); | |
| 471 EXPECT_EQ(now, score_.last_engagement_time_); | |
| 472 EXPECT_EQ(now, score_.last_shortcut_launch_time_); | |
| 473 } | |
| 474 | |
| 475 class SiteEngagementServiceTest : public ChromeRenderViewHostTestHarness { | 100 class SiteEngagementServiceTest : public ChromeRenderViewHostTestHarness { |
| 476 public: | 101 public: |
| 477 void SetUp() override { | 102 void SetUp() override { |
| 478 ChromeRenderViewHostTestHarness::SetUp(); | 103 ChromeRenderViewHostTestHarness::SetUp(); |
| 479 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 104 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 480 g_temp_history_dir = temp_dir_.path(); | 105 g_temp_history_dir = temp_dir_.path(); |
| 481 HistoryServiceFactory::GetInstance()->SetTestingFactory( | 106 HistoryServiceFactory::GetInstance()->SetTestingFactory( |
| 482 profile(), &BuildTestHistoryService); | 107 profile(), &BuildTestHistoryService); |
| 483 SiteEngagementScore::SetParamValuesForTesting(); | 108 SiteEngagementScore::SetParamValuesForTesting(); |
| 484 } | 109 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 507 ->TestDidNavigate(web_contents()->GetMainFrame(), 1, pending_id, true, | 132 ->TestDidNavigate(web_contents()->GetMainFrame(), 1, pending_id, true, |
| 508 url, transition); | 133 url, transition); |
| 509 EXPECT_EQ(prev_score, service->GetScore(url)); | 134 EXPECT_EQ(prev_score, service->GetScore(url)); |
| 510 } | 135 } |
| 511 | 136 |
| 512 private: | 137 private: |
| 513 base::ScopedTempDir temp_dir_; | 138 base::ScopedTempDir temp_dir_; |
| 514 }; | 139 }; |
| 515 | 140 |
| 516 TEST_F(SiteEngagementServiceTest, GetMedianEngagement) { | 141 TEST_F(SiteEngagementServiceTest, GetMedianEngagement) { |
| 517 SiteEngagementService* service = | 142 SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| 518 SiteEngagementServiceFactory::GetForProfile(profile()); | |
| 519 ASSERT_TRUE(service); | 143 ASSERT_TRUE(service); |
| 520 | 144 |
| 521 GURL url1("http://www.google.com/"); | 145 GURL url1("http://www.google.com/"); |
| 522 GURL url2("https://www.google.com/"); | 146 GURL url2("https://www.google.com/"); |
| 523 GURL url3("https://drive.google.com/"); | 147 GURL url3("https://drive.google.com/"); |
| 524 GURL url4("https://maps.google.com/"); | 148 GURL url4("https://maps.google.com/"); |
| 525 GURL url5("https://youtube.com/"); | 149 GURL url5("https://youtube.com/"); |
| 526 GURL url6("https://images.google.com/"); | 150 GURL url6("https://images.google.com/"); |
| 527 | 151 |
| 528 { | 152 { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 std::map<GURL, double> score_map = service->GetScoreMap(); | 198 std::map<GURL, double> score_map = service->GetScoreMap(); |
| 575 EXPECT_TRUE(6 == score_map.size()); | 199 EXPECT_TRUE(6 == score_map.size()); |
| 576 EXPECT_DOUBLE_EQ(1.9, service->GetMedianEngagement(score_map)); | 200 EXPECT_DOUBLE_EQ(1.9, service->GetMedianEngagement(score_map)); |
| 577 } | 201 } |
| 578 } | 202 } |
| 579 | 203 |
| 580 // Tests that the Site Engagement service is hooked up properly to navigations | 204 // Tests that the Site Engagement service is hooked up properly to navigations |
| 581 // by performing two navigations and checking the engagement score increases | 205 // by performing two navigations and checking the engagement score increases |
| 582 // both times. | 206 // both times. |
| 583 TEST_F(SiteEngagementServiceTest, ScoreIncrementsOnPageRequest) { | 207 TEST_F(SiteEngagementServiceTest, ScoreIncrementsOnPageRequest) { |
| 584 SiteEngagementService* service = | 208 SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| 585 SiteEngagementServiceFactory::GetForProfile(profile()); | |
| 586 ASSERT_TRUE(service); | 209 ASSERT_TRUE(service); |
| 587 | 210 |
| 588 // Create the helper manually since it isn't present when a tab isn't created. | 211 // Create the helper manually since it isn't present when a tab isn't created. |
| 589 SiteEngagementHelper::CreateForWebContents(web_contents()); | 212 SiteEngagementService::Helper::CreateForWebContents(web_contents()); |
| 590 | 213 |
| 591 GURL url("http://www.google.com/"); | 214 GURL url("http://www.google.com/"); |
| 592 EXPECT_EQ(0, service->GetScore(url)); | 215 EXPECT_EQ(0, service->GetScore(url)); |
| 593 NavigateWithTransitionAndExpectHigherScore(service, url, | 216 NavigateWithTransitionAndExpectHigherScore(service, url, |
| 594 ui::PAGE_TRANSITION_TYPED); | 217 ui::PAGE_TRANSITION_TYPED); |
| 595 NavigateWithTransitionAndExpectHigherScore(service, url, | 218 NavigateWithTransitionAndExpectHigherScore(service, url, |
| 596 ui::PAGE_TRANSITION_AUTO_BOOKMARK); | 219 ui::PAGE_TRANSITION_AUTO_BOOKMARK); |
| 597 } | 220 } |
| 598 | 221 |
| 599 // Expect that site engagement scores for several sites are correctly | 222 // Expect that site engagement scores for several sites are correctly |
| 600 // aggregated during navigation events. | 223 // aggregated during navigation events. |
| 601 TEST_F(SiteEngagementServiceTest, GetTotalNavigationPoints) { | 224 TEST_F(SiteEngagementServiceTest, GetTotalNavigationPoints) { |
| 602 SiteEngagementService* service = | 225 SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| 603 SiteEngagementServiceFactory::GetForProfile(profile()); | |
| 604 ASSERT_TRUE(service); | 226 ASSERT_TRUE(service); |
| 605 | 227 |
| 606 // The https and http versions of www.google.com should be separate. | 228 // The https and http versions of www.google.com should be separate. |
| 607 GURL url1("https://www.google.com/"); | 229 GURL url1("https://www.google.com/"); |
| 608 GURL url2("http://www.google.com/"); | 230 GURL url2("http://www.google.com/"); |
| 609 GURL url3("http://drive.google.com/"); | 231 GURL url3("http://drive.google.com/"); |
| 610 | 232 |
| 611 EXPECT_EQ(0, service->GetScore(url1)); | 233 EXPECT_EQ(0, service->GetScore(url1)); |
| 612 EXPECT_EQ(0, service->GetScore(url2)); | 234 EXPECT_EQ(0, service->GetScore(url2)); |
| 613 EXPECT_EQ(0, service->GetScore(url3)); | 235 EXPECT_EQ(0, service->GetScore(url3)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 629 EXPECT_EQ(0.5, service->GetScore(url3)); | 251 EXPECT_EQ(0.5, service->GetScore(url3)); |
| 630 EXPECT_EQ(2.5, service->GetTotalEngagementPoints()); | 252 EXPECT_EQ(2.5, service->GetTotalEngagementPoints()); |
| 631 | 253 |
| 632 service->HandleNavigation(url1, ui::PAGE_TRANSITION_GENERATED); | 254 service->HandleNavigation(url1, ui::PAGE_TRANSITION_GENERATED); |
| 633 service->HandleNavigation(url1, ui::PAGE_TRANSITION_TYPED); | 255 service->HandleNavigation(url1, ui::PAGE_TRANSITION_TYPED); |
| 634 EXPECT_EQ(1.5, service->GetScore(url1)); | 256 EXPECT_EQ(1.5, service->GetScore(url1)); |
| 635 EXPECT_EQ(3.5, service->GetTotalEngagementPoints()); | 257 EXPECT_EQ(3.5, service->GetTotalEngagementPoints()); |
| 636 } | 258 } |
| 637 | 259 |
| 638 TEST_F(SiteEngagementServiceTest, GetTotalUserInputPoints) { | 260 TEST_F(SiteEngagementServiceTest, GetTotalUserInputPoints) { |
| 639 SiteEngagementService* service = | 261 SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| 640 SiteEngagementServiceFactory::GetForProfile(profile()); | |
| 641 ASSERT_TRUE(service); | 262 ASSERT_TRUE(service); |
| 642 | 263 |
| 643 // The https and http versions of www.google.com should be separate. | 264 // The https and http versions of www.google.com should be separate. |
| 644 GURL url1("https://www.google.com/"); | 265 GURL url1("https://www.google.com/"); |
| 645 GURL url2("http://www.google.com/"); | 266 GURL url2("http://www.google.com/"); |
| 646 GURL url3("http://drive.google.com/"); | 267 GURL url3("http://drive.google.com/"); |
| 647 | 268 |
| 648 EXPECT_EQ(0, service->GetScore(url1)); | 269 EXPECT_EQ(0, service->GetScore(url1)); |
| 649 EXPECT_EQ(0, service->GetScore(url2)); | 270 EXPECT_EQ(0, service->GetScore(url2)); |
| 650 EXPECT_EQ(0, service->GetScore(url3)); | 271 EXPECT_EQ(0, service->GetScore(url3)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 SiteEngagementMetrics::kEngagementTypeHistogram, | 323 SiteEngagementMetrics::kEngagementTypeHistogram, |
| 703 SiteEngagementMetrics::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, 1); | 324 SiteEngagementMetrics::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, 1); |
| 704 | 325 |
| 705 service->AddPoints(url1, 2.0); | 326 service->AddPoints(url1, 2.0); |
| 706 service->AddPoints(url2, 2.0); | 327 service->AddPoints(url2, 2.0); |
| 707 clock->SetNow(current_day); | 328 clock->SetNow(current_day); |
| 708 service->SetLastShortcutLaunchTime(url2); | 329 service->SetLastShortcutLaunchTime(url2); |
| 709 | 330 |
| 710 histograms.ExpectTotalCount( | 331 histograms.ExpectTotalCount( |
| 711 SiteEngagementMetrics::kDaysSinceLastShortcutLaunchHistogram, 1); | 332 SiteEngagementMetrics::kDaysSinceLastShortcutLaunchHistogram, 1); |
| 712 histograms.ExpectTotalCount( | 333 histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 713 SiteEngagementMetrics::kEngagementTypeHistogram, 4); | 334 4); |
| 714 histograms.ExpectBucketCount( | 335 histograms.ExpectBucketCount( |
| 715 SiteEngagementMetrics::kEngagementTypeHistogram, | 336 SiteEngagementMetrics::kEngagementTypeHistogram, |
| 716 SiteEngagementMetrics::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, 2); | 337 SiteEngagementMetrics::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, 2); |
| 717 histograms.ExpectBucketCount( | 338 histograms.ExpectBucketCount( |
| 718 SiteEngagementMetrics::kEngagementTypeHistogram, | 339 SiteEngagementMetrics::kEngagementTypeHistogram, |
| 719 SiteEngagementMetrics::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 2); | 340 SiteEngagementMetrics::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 2); |
| 720 | 341 |
| 721 EXPECT_DOUBLE_EQ(2.0, service->GetScore(url1)); | 342 EXPECT_DOUBLE_EQ(2.0, service->GetScore(url1)); |
| 722 EXPECT_DOUBLE_EQ(7.0, service->GetScore(url2)); | 343 EXPECT_DOUBLE_EQ(7.0, service->GetScore(url2)); |
| 723 | 344 |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 | 697 |
| 1077 score_map = service->GetScoreMap(); | 698 score_map = service->GetScoreMap(); |
| 1078 EXPECT_EQ(0u, score_map.size()); | 699 EXPECT_EQ(0u, score_map.size()); |
| 1079 EXPECT_EQ(0, service->GetScore(url1)); | 700 EXPECT_EQ(0, service->GetScore(url1)); |
| 1080 } | 701 } |
| 1081 } | 702 } |
| 1082 | 703 |
| 1083 TEST_F(SiteEngagementServiceTest, NavigationAccumulation) { | 704 TEST_F(SiteEngagementServiceTest, NavigationAccumulation) { |
| 1084 GURL url("https://www.google.com/"); | 705 GURL url("https://www.google.com/"); |
| 1085 | 706 |
| 1086 SiteEngagementService* service = | 707 SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| 1087 SiteEngagementServiceFactory::GetForProfile(profile()); | |
| 1088 ASSERT_TRUE(service); | 708 ASSERT_TRUE(service); |
| 1089 | 709 |
| 1090 // Create the helper manually since it isn't present when a tab isn't created. | 710 // Create the helper manually since it isn't present when a tab isn't created. |
| 1091 SiteEngagementHelper::CreateForWebContents(web_contents()); | 711 SiteEngagementService::Helper::CreateForWebContents(web_contents()); |
| 1092 | 712 |
| 1093 // Only direct navigation should trigger engagement. | 713 // Only direct navigation should trigger engagement. |
| 1094 NavigateWithTransitionAndExpectHigherScore(service, url, | 714 NavigateWithTransitionAndExpectHigherScore(service, url, |
| 1095 ui::PAGE_TRANSITION_TYPED); | 715 ui::PAGE_TRANSITION_TYPED); |
| 1096 NavigateWithTransitionAndExpectHigherScore(service, url, | 716 NavigateWithTransitionAndExpectHigherScore(service, url, |
| 1097 ui::PAGE_TRANSITION_GENERATED); | 717 ui::PAGE_TRANSITION_GENERATED); |
| 1098 NavigateWithTransitionAndExpectHigherScore(service, url, | 718 NavigateWithTransitionAndExpectHigherScore(service, url, |
| 1099 ui::PAGE_TRANSITION_AUTO_BOOKMARK); | 719 ui::PAGE_TRANSITION_AUTO_BOOKMARK); |
| 1100 NavigateWithTransitionAndExpectHigherScore( | 720 NavigateWithTransitionAndExpectHigherScore( |
| 1101 service, url, ui::PAGE_TRANSITION_KEYWORD_GENERATED); | 721 service, url, ui::PAGE_TRANSITION_KEYWORD_GENERATED); |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 0, 2); | 1065 0, 2); |
| 1446 | 1066 |
| 1447 // Add more points and ensure no more samples are present. | 1067 // Add more points and ensure no more samples are present. |
| 1448 service->AddPoints(origin1, 0.01); | 1068 service->AddPoints(origin1, 0.01); |
| 1449 service->AddPoints(origin2, 0.01); | 1069 service->AddPoints(origin2, 0.01); |
| 1450 histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram, | 1070 histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedFromHistogram, |
| 1451 4); | 1071 4); |
| 1452 histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram, | 1072 histograms.ExpectTotalCount(SiteEngagementMetrics::kScoreDecayedToHistogram, |
| 1453 4); | 1073 4); |
| 1454 } | 1074 } |
| OLD | NEW |