OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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_score.h" | 5 #include "chrome/browser/engagement/site_engagement_score.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/time/clock.h" | 12 #include "base/time/clock.h" |
13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
16 #include "chrome/browser/engagement/site_engagement_metrics.h" | 16 #include "chrome/browser/engagement/site_engagement_metrics.h" |
17 #include "components/content_settings/core/browser/host_content_settings_map.h" | 17 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 18 #include "components/content_settings/core/common/content_settings.h" |
| 19 #include "components/content_settings/core/common/content_settings_types.h" |
18 #include "components/variations/variations_associated_data.h" | 20 #include "components/variations/variations_associated_data.h" |
19 | 21 |
20 namespace { | 22 namespace { |
21 | 23 |
22 // Delta within which to consider scores equal. | 24 // Delta within which to consider scores equal. |
23 const double kScoreDelta = 0.001; | 25 const double kScoreDelta = 0.001; |
24 | 26 |
25 // Delta within which to consider internal time values equal. Internal time | 27 // Delta within which to consider internal time values equal. Internal time |
26 // values are in microseconds, so this delta comes out at one second. | 28 // values are in microseconds, so this delta comes out at one second. |
27 const double kTimeDelta = 1000000; | 29 const double kTimeDelta = 1000000; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 param_values[VISIBLE_MEDIA_POINTS] = {"visible_media_playing_points", 0.06}; | 83 param_values[VISIBLE_MEDIA_POINTS] = {"visible_media_playing_points", 0.06}; |
82 param_values[HIDDEN_MEDIA_POINTS] = {"hidden_media_playing_points", 0.01}; | 84 param_values[HIDDEN_MEDIA_POINTS] = {"hidden_media_playing_points", 0.01}; |
83 param_values[WEB_APP_INSTALLED_POINTS] = {"web_app_installed_points", 5}; | 85 param_values[WEB_APP_INSTALLED_POINTS] = {"web_app_installed_points", 5}; |
84 param_values[FIRST_DAILY_ENGAGEMENT] = {"first_daily_engagement_points", 1.5}; | 86 param_values[FIRST_DAILY_ENGAGEMENT] = {"first_daily_engagement_points", 1.5}; |
85 param_values[BOOTSTRAP_POINTS] = {"bootstrap_points", 24}; | 87 param_values[BOOTSTRAP_POINTS] = {"bootstrap_points", 24}; |
86 param_values[MEDIUM_ENGAGEMENT_BOUNDARY] = {"medium_engagement_boundary", 15}; | 88 param_values[MEDIUM_ENGAGEMENT_BOUNDARY] = {"medium_engagement_boundary", 15}; |
87 param_values[HIGH_ENGAGEMENT_BOUNDARY] = {"high_engagement_boundary", 50}; | 89 param_values[HIGH_ENGAGEMENT_BOUNDARY] = {"high_engagement_boundary", 50}; |
88 param_values[MAX_DECAYS_PER_SCORE] = {"max_decays_per_score", 4}; | 90 param_values[MAX_DECAYS_PER_SCORE] = {"max_decays_per_score", 4}; |
89 param_values[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS] = { | 91 param_values[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS] = { |
90 "last_engagement_grace_period_in_hours", 1}; | 92 "last_engagement_grace_period_in_hours", 1}; |
| 93 param_values[NOTIFICATION_PERMISSION_POINTS] = { |
| 94 "notification_permission_points", 5}; |
91 return param_values; | 95 return param_values; |
92 } | 96 } |
93 | 97 |
94 double SiteEngagementScore::GetMaxPointsPerDay() { | 98 double SiteEngagementScore::GetMaxPointsPerDay() { |
95 return GetParamValues()[MAX_POINTS_PER_DAY].second; | 99 return GetParamValues()[MAX_POINTS_PER_DAY].second; |
96 } | 100 } |
97 | 101 |
98 double SiteEngagementScore::GetDecayPeriodInHours() { | 102 double SiteEngagementScore::GetDecayPeriodInHours() { |
99 return GetParamValues()[DECAY_PERIOD_IN_HOURS].second; | 103 return GetParamValues()[DECAY_PERIOD_IN_HOURS].second; |
100 } | 104 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 } | 152 } |
149 | 153 |
150 double SiteEngagementScore::GetMaxDecaysPerScore() { | 154 double SiteEngagementScore::GetMaxDecaysPerScore() { |
151 return GetParamValues()[MAX_DECAYS_PER_SCORE].second; | 155 return GetParamValues()[MAX_DECAYS_PER_SCORE].second; |
152 } | 156 } |
153 | 157 |
154 double SiteEngagementScore::GetLastEngagementGracePeriodInHours() { | 158 double SiteEngagementScore::GetLastEngagementGracePeriodInHours() { |
155 return GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second; | 159 return GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second; |
156 } | 160 } |
157 | 161 |
| 162 double SiteEngagementScore::GetNotificationPermissionPoints() { |
| 163 return GetParamValues()[NOTIFICATION_PERMISSION_POINTS].second; |
| 164 } |
| 165 |
158 // static | 166 // static |
159 void SiteEngagementScore::UpdateFromVariations(const char* param_name) { | 167 void SiteEngagementScore::UpdateFromVariations(const char* param_name) { |
160 double param_vals[MAX_VARIATION]; | 168 double param_vals[MAX_VARIATION]; |
161 | 169 |
162 for (int i = 0; i < MAX_VARIATION; ++i) { | 170 for (int i = 0; i < MAX_VARIATION; ++i) { |
163 std::string param_string = variations::GetVariationParamValue( | 171 std::string param_string = variations::GetVariationParamValue( |
164 param_name, GetParamValues()[i].first); | 172 param_name, GetParamValues()[i].first); |
165 | 173 |
166 // Bail out if we didn't get a param string for the key, or if we couldn't | 174 // Bail out if we didn't get a param string for the key, or if we couldn't |
167 // convert the param string to a double, or if we get a negative value. | 175 // convert the param string to a double, or if we get a negative value. |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 SiteEngagementScore::SiteEngagementScore( | 334 SiteEngagementScore::SiteEngagementScore( |
327 base::Clock* clock, | 335 base::Clock* clock, |
328 const GURL& origin, | 336 const GURL& origin, |
329 std::unique_ptr<base::DictionaryValue> score_dict) | 337 std::unique_ptr<base::DictionaryValue> score_dict) |
330 : clock_(clock), | 338 : clock_(clock), |
331 raw_score_(0), | 339 raw_score_(0), |
332 points_added_today_(0), | 340 points_added_today_(0), |
333 last_engagement_time_(), | 341 last_engagement_time_(), |
334 last_shortcut_launch_time_(), | 342 last_shortcut_launch_time_(), |
335 score_dict_(score_dict.release()), | 343 score_dict_(score_dict.release()), |
336 origin_(origin) { | 344 origin_(origin), |
| 345 settings_map_(nullptr) { |
337 if (!score_dict_) | 346 if (!score_dict_) |
338 return; | 347 return; |
339 | 348 |
340 score_dict_->GetDouble(kRawScoreKey, &raw_score_); | 349 score_dict_->GetDouble(kRawScoreKey, &raw_score_); |
341 score_dict_->GetDouble(kPointsAddedTodayKey, &points_added_today_); | 350 score_dict_->GetDouble(kPointsAddedTodayKey, &points_added_today_); |
342 | 351 |
343 double internal_time; | 352 double internal_time; |
344 if (score_dict_->GetDouble(kLastEngagementTimeKey, &internal_time)) | 353 if (score_dict_->GetDouble(kLastEngagementTimeKey, &internal_time)) |
345 last_engagement_time_ = base::Time::FromInternalValue(internal_time); | 354 last_engagement_time_ = base::Time::FromInternalValue(internal_time); |
346 if (score_dict_->GetDouble(kLastShortcutLaunchTimeKey, &internal_time)) | 355 if (score_dict_->GetDouble(kLastShortcutLaunchTimeKey, &internal_time)) |
347 last_shortcut_launch_time_ = base::Time::FromInternalValue(internal_time); | 356 last_shortcut_launch_time_ = base::Time::FromInternalValue(internal_time); |
348 } | 357 } |
349 | 358 |
350 double SiteEngagementScore::DecayedScore() const { | 359 double SiteEngagementScore::DecayedScore() const { |
351 // Note that users can change their clock, so from this system's perspective | 360 // Note that users can change their clock, so from this system's perspective |
352 // time can go backwards. If that does happen and the system detects that the | 361 // time can go backwards. If that does happen and the system detects that the |
353 // current day is earlier than the last engagement, no decay (or growth) is | 362 // current day is earlier than the last engagement, no decay (or growth) is |
354 // applied. | 363 // applied. |
355 int hours_since_engagement = | 364 int hours_since_engagement = |
356 (clock_->Now() - last_engagement_time_).InHours(); | 365 (clock_->Now() - last_engagement_time_).InHours(); |
357 if (hours_since_engagement < 0) | 366 if (hours_since_engagement < 0) |
358 return raw_score_; | 367 return raw_score_; |
359 | 368 |
360 int periods = hours_since_engagement / GetDecayPeriodInHours(); | 369 int periods = hours_since_engagement / GetDecayPeriodInHours(); |
361 return std::max(0.0, raw_score_ * pow(GetDecayProportion(), periods) - | 370 return std::max(0.0, raw_score_ * pow(GetDecayProportion(), periods) - |
362 periods * GetDecayPoints()); | 371 periods * GetDecayPoints()); |
363 } | 372 } |
364 | 373 |
365 double SiteEngagementScore::BonusScore() const { | 374 double SiteEngagementScore::BonusScore() const { |
| 375 double bonus = 0; |
366 int days_since_shortcut_launch = | 376 int days_since_shortcut_launch = |
367 (clock_->Now() - last_shortcut_launch_time_).InDays(); | 377 (clock_->Now() - last_shortcut_launch_time_).InDays(); |
368 if (days_since_shortcut_launch <= kMaxDaysSinceShortcutLaunch) | 378 if (days_since_shortcut_launch <= kMaxDaysSinceShortcutLaunch) |
369 return GetWebAppInstalledPoints(); | 379 bonus += GetWebAppInstalledPoints(); |
370 | 380 |
371 return 0; | 381 // TODO(dominickn, raymes): call PermissionManager::GetPermissionStatus when |
| 382 // the PermissionManager is thread-safe. |
| 383 if (settings_map_ && settings_map_->GetContentSetting( |
| 384 origin_, GURL(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, |
| 385 std::string()) == CONTENT_SETTING_ALLOW) { |
| 386 bonus += GetNotificationPermissionPoints(); |
| 387 } |
| 388 |
| 389 return bonus; |
372 } | 390 } |
373 | 391 |
374 void SiteEngagementScore::SetParamValuesForTesting() { | 392 void SiteEngagementScore::SetParamValuesForTesting() { |
375 GetParamValues()[MAX_POINTS_PER_DAY].second = 5; | 393 GetParamValues()[MAX_POINTS_PER_DAY].second = 5; |
376 GetParamValues()[DECAY_PERIOD_IN_HOURS].second = 7 * 24; | 394 GetParamValues()[DECAY_PERIOD_IN_HOURS].second = 7 * 24; |
377 GetParamValues()[DECAY_POINTS].second = 5; | 395 GetParamValues()[DECAY_POINTS].second = 5; |
378 GetParamValues()[NAVIGATION_POINTS].second = 0.5; | 396 GetParamValues()[NAVIGATION_POINTS].second = 0.5; |
379 GetParamValues()[USER_INPUT_POINTS].second = 0.05; | 397 GetParamValues()[USER_INPUT_POINTS].second = 0.05; |
380 GetParamValues()[VISIBLE_MEDIA_POINTS].second = 0.02; | 398 GetParamValues()[VISIBLE_MEDIA_POINTS].second = 0.02; |
381 GetParamValues()[HIDDEN_MEDIA_POINTS].second = 0.01; | 399 GetParamValues()[HIDDEN_MEDIA_POINTS].second = 0.01; |
382 GetParamValues()[WEB_APP_INSTALLED_POINTS].second = 5; | 400 GetParamValues()[WEB_APP_INSTALLED_POINTS].second = 5; |
383 GetParamValues()[BOOTSTRAP_POINTS].second = 8; | 401 GetParamValues()[BOOTSTRAP_POINTS].second = 8; |
384 GetParamValues()[MEDIUM_ENGAGEMENT_BOUNDARY].second = 5; | 402 GetParamValues()[MEDIUM_ENGAGEMENT_BOUNDARY].second = 5; |
385 GetParamValues()[HIGH_ENGAGEMENT_BOUNDARY].second = 50; | 403 GetParamValues()[HIGH_ENGAGEMENT_BOUNDARY].second = 50; |
386 GetParamValues()[MAX_DECAYS_PER_SCORE].second = 1; | 404 GetParamValues()[MAX_DECAYS_PER_SCORE].second = 1; |
387 GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second = 72; | 405 GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second = 72; |
| 406 GetParamValues()[NOTIFICATION_PERMISSION_POINTS].second = 5; |
388 | 407 |
389 // This is set to values that avoid interference with tests and are set when | 408 // This is set to values that avoid interference with tests and are set when |
390 // testing these features. | 409 // testing these features. |
391 GetParamValues()[FIRST_DAILY_ENGAGEMENT].second = 0; | 410 GetParamValues()[FIRST_DAILY_ENGAGEMENT].second = 0; |
392 GetParamValues()[DECAY_PROPORTION].second = 1; | 411 GetParamValues()[DECAY_PROPORTION].second = 1; |
393 GetParamValues()[SCORE_CLEANUP_THRESHOLD].second = 0; | 412 GetParamValues()[SCORE_CLEANUP_THRESHOLD].second = 0; |
394 } | 413 } |
OLD | NEW |