1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_SCORE_H_
#define COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_SCORE_H_
#include <array>
#include <optional>
#include <string>
#include <utility>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/site_engagement/core/mojom/site_engagement_details.mojom-forward.h"
#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom-forward.h"
#include "url/gurl.h"
namespace base {
class Clock;
}
class HostContentSettingsMap;
namespace site_engagement {
class SiteEngagementScore {
public:
// The parameters which can be varied via field trial.
enum Variation {
// The maximum number of points that can be accrued in one day.
MAX_POINTS_PER_DAY = 0,
// The period over which site engagement decays.
DECAY_PERIOD_IN_HOURS,
// The number of points to decay per period.
DECAY_POINTS,
// The proportion [0-1] which the current engagement value is multiplied by
// at each decay period, before subtracting DECAY_POINTS.
DECAY_PROPORTION,
// A score will be erased from the engagement system if it's less than this
// value.
SCORE_CLEANUP_THRESHOLD,
// The number of points given for navigations.
NAVIGATION_POINTS,
// The number of points given for user input.
USER_INPUT_POINTS,
// The number of points given for media playing. Initially calibrated such
// that at least 30 minutes of foreground media would be required to allow a
// site to reach the daily engagement maximum.
VISIBLE_MEDIA_POINTS,
HIDDEN_MEDIA_POINTS,
// The number of points added to engagement when a site is launched from
// homescreen or added as a bookmark app. This bonus will apply for ten days
// following a launch; each new launch resets the ten days.
WEB_APP_INSTALLED_POINTS,
// The number of points given for the first engagement event of the day for
// each site.
FIRST_DAILY_ENGAGEMENT,
// The number of points that the engagement service must accumulate to be
// considered 'useful'.
BOOTSTRAP_POINTS,
// The boundaries between low/medium and medium/high engagement as returned
// by GetEngagementLevel().
MEDIUM_ENGAGEMENT_BOUNDARY,
HIGH_ENGAGEMENT_BOUNDARY,
// The maximum number of decays that a SiteEngagementScore can incur before
// entering a grace period. MAX_DECAYS_PER_SCORE * DECAY_PERIOD_IN_DAYS is
// the max decay period, i.e. the maximum duration permitted for
// (clock_->Now() - score.last_engagement_time()).
MAX_DECAYS_PER_SCORE,
// If a SiteEngagamentScore has not been accessed or updated for a period
// longer than the max decay period + LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS
// (see above), its last engagement time will be reset to be max decay
// period prior to clock_->Now().
LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS,
// The number of points given for interacting with a displayed notification.
NOTIFICATION_INTERACTION_POINTS,
MAX_VARIATION
};
// The maximum number of points that are allowed.
static const double kMaxPoints;
static double GetMaxPointsPerDay();
static double GetDecayPeriodInHours();
static double GetDecayPoints();
static double GetDecayProportion();
static double GetScoreCleanupThreshold();
static double GetNavigationPoints();
static double GetUserInputPoints();
static double GetVisibleMediaPoints();
static double GetHiddenMediaPoints();
static double GetWebAppInstalledPoints();
static double GetFirstDailyEngagementPoints();
static double GetBootstrapPoints();
static double GetMediumEngagementBoundary();
static double GetHighEngagementBoundary();
static double GetMaxDecaysPerScore();
static double GetLastEngagementGracePeriodInHours();
static double GetNotificationInteractionPoints();
// Sets fixed parameter values for testing site engagement. Ensure that any
// newly added parameters receive a fixed value here.
static void SetParamValuesForTesting();
// Update the default engagement settings via variations.
static void UpdateFromVariations(const char* param_name);
// The SiteEngagementScore does not take ownership of |clock|. It is the
// responsibility of the caller to make sure |clock| outlives this
// SiteEngagementScore.
SiteEngagementScore(base::Clock* clock,
const GURL& origin,
HostContentSettingsMap* settings);
SiteEngagementScore(SiteEngagementScore&& other);
SiteEngagementScore(const SiteEngagementScore&) = delete;
SiteEngagementScore& operator=(const SiteEngagementScore&) = delete;
~SiteEngagementScore();
SiteEngagementScore& operator=(SiteEngagementScore&& other);
// Adds |points| to this score, respecting daily limits and the maximum
// possible score. Decays the score if it has not been updated recently
// enough.
void AddPoints(double points);
// Returns the total score, taking into account the base, bonus and maximum
// values.
double GetTotalScore() const;
// Returns a structure containing the origin URL and score, and details
// of the base and bonus scores. Note that the |score| is limited to
// kMaxPoints, while the detailed scores are returned raw.
mojom::SiteEngagementDetails GetDetails() const;
// Writes the values in this score into |settings_map_|.
void Commit();
// Returns the discrete engagement level for this score.
blink::mojom::EngagementLevel GetEngagementLevel() const;
// Returns true if the maximum number of points today has been added.
bool MaxPointsPerDayAdded() const;
// Resets the score to |points| and resets the daily point limit. If
// |updated_time| is non-null, sets the last engagement time to that value.
void Reset(double points, const base::Time updated_time);
// Get/set the last time this origin was launched from an installed shortcut.
base::Time last_shortcut_launch_time() const {
return last_shortcut_launch_time_;
}
void set_last_shortcut_launch_time(const base::Time& time) {
last_shortcut_launch_time_ = time;
}
// Get/set the last time this origin recorded an engagement change.
base::Time last_engagement_time() const { return last_engagement_time_; }
void SetLastEngagementTime(const base::Time& time);
private:
FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, FirstDailyEngagementBonus);
FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, PartiallyEmptyDictionary);
FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, PopulatedDictionary);
FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, Reset);
friend class SiteEngagementScoreTest;
friend class SiteEngagementServiceTest;
using ParamValues = std::array<std::pair<std::string, double>, MAX_VARIATION>;
// Array holding the values corresponding to each item in Variation array.
static ParamValues& GetParamValues();
// Keys used in the content settings dictionary.
static const char kRawScoreKey[];
static const char kPointsAddedTodayKey[];
static const char kLastEngagementTimeKey[];
static const char kLastShortcutLaunchTimeKey[];
// This version of the constructor is used in unit tests.
SiteEngagementScore(base::Clock* clock,
const GURL& origin,
std::optional<base::Value::Dict> score_dict);
// Determine the score, accounting for any decay.
double DecayedScore() const;
// Determine bonus from being installed, and having been launched recently..
double BonusIfShortcutLaunched() const;
// Updates the content settings dictionary |score_dict| with the current score
// fields. Returns true if |score_dict| changed, otherwise return false.
bool UpdateScoreDict(base::Value::Dict& score_dict);
// The clock used to vend times. Enables time travelling in tests. Owned by
// the SiteEngagementService.
// `clock_` is not a raw_ptr<...> for performance reasons (based on analysis
// of sampling profiler data).
RAW_PTR_EXCLUSION base::Clock* clock_;
// |raw_score_| is the score before any decay is applied.
double raw_score_;
// The points added 'today' are tracked to avoid adding more than
// kMaxPointsPerDay on any one day. 'Today' is defined in local time.
double points_added_today_;
// The last time the score was updated for engagement. Used in conjunction
// with |points_added_today_| to avoid adding more than kMaxPointsPerDay on
// any one day.
base::Time last_engagement_time_;
// The last time the site with this score was launched from an installed
// shortcut.
base::Time last_shortcut_launch_time_;
// The dictionary that represents this engagement score.
std::optional<base::Value::Dict> score_dict_;
// The origin this score represents.
GURL origin_;
// The settings to write this score to when Commit() is called.
// `settings_map_` is not a raw_ptr<...> for performance reasons (based on
// analysis of sampling profiler data).
RAW_PTR_EXCLUSION HostContentSettingsMap* settings_map_;
};
} // namespace site_engagement
#endif // COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_SCORE_H_
|