Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(769)

Unified Diff: chrome/browser/engagement/site_engagement_service.cc

Issue 2427343002: Make the site engagement service more robust to clock changes and time inconsistencies. (Closed)
Patch Set: Address nit Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/engagement/site_engagement_service.cc
diff --git a/chrome/browser/engagement/site_engagement_service.cc b/chrome/browser/engagement/site_engagement_service.cc
index 4437b54d108e40c9691a0789fe3473d65a794641..a8c1bfb4db53630d8dfc0a8b1337a527a9e3ebbf 100644
--- a/chrome/browser/engagement/site_engagement_service.cc
+++ b/chrome/browser/engagement/site_engagement_service.cc
@@ -289,10 +289,6 @@ void SiteEngagementService::AfterStartupTask() {
void SiteEngagementService::CleanupEngagementScores(
bool update_last_engagement_time) const {
- // This method should not be called with |update_last_engagement_time| = true
- // if the last engagement time isn't stale.
- DCHECK(!update_last_engagement_time || IsLastEngagementStale());
-
HostContentSettingsMap* settings_map =
HostContentSettingsMapFactory::GetForProfile(profile_);
std::unique_ptr<ContentSettingsForOneType> engagement_settings =
@@ -304,25 +300,51 @@ void SiteEngagementService::CleanupEngagementScores(
base::Time last_engagement_time = GetLastEngagementTime();
base::Time rebase_time = now - GetMaxDecayPeriod();
base::Time new_last_engagement_time;
+
+ // If |update_last_engagement_time| is true, we must have either:
+ // a) last_engagement_time is in the future; OR
+ // b) last_engagement_time < rebase_time < now
+ DCHECK(!update_last_engagement_time || last_engagement_time >= now ||
+ (last_engagement_time < rebase_time && rebase_time < now));
+
+ // Cap |last_engagement_time| at |now| if it is in the future. This ensures
+ // that we use sane offsets when a user has adjusted their clock backwards and
+ // have a mix of scores prior to and after |now|.
+ if (last_engagement_time > now)
+ last_engagement_time = now;
+
for (const auto& site : *engagement_settings) {
GURL origin(site.primary_pattern.ToString());
if (origin.is_valid()) {
SiteEngagementScore score = CreateEngagementScore(origin);
if (update_last_engagement_time) {
- // Work out the offset between this score's last engagement time and the
- // last time the service recorded any engagement. Set the score's last
- // engagement time to rebase_time - offset to preserve its state,
- // relative to the rebase date. This ensures that the score will decay
- // the next time it is used, but will not decay too much.
- DCHECK_LE(score.last_engagement_time(), rebase_time);
- base::TimeDelta offset =
- last_engagement_time - score.last_engagement_time();
- base::Time rebase_score_time = rebase_time - offset;
- score.set_last_engagement_time(rebase_score_time);
- if (rebase_score_time > new_last_engagement_time)
- new_last_engagement_time = rebase_score_time;
-
+ // Catch cases of users moving their clocks, or a potential race where
+ // a score content setting is written out to prefs, but the updated
+ // |last_engagement_time| was not written, as both are lossy
+ // preferences. |rebase_time| is strictly in the past, so any score with
+ // a last updated time in the future is caught by this branch.
+ if (score.last_engagement_time() > rebase_time) {
+ score.set_last_engagement_time(now);
+ } else if (score.last_engagement_time() > last_engagement_time) {
+ // This score is newer than |last_engagement_time|, but older than
+ // |rebase_time|. It should still be rebased with no offset as we
+ // don't accurately know what the offset should be.
+ score.set_last_engagement_time(rebase_time);
+ } else {
+ // Work out the offset between this score's last engagement time and
+ // the last time the service recorded any engagement. Set the score's
+ // last engagement time to rebase_time - offset to preserve its state,
+ // relative to the rebase date. This ensures that the score will decay
+ // the next time it is used, but will not decay too much.
+ base::TimeDelta offset =
+ last_engagement_time - score.last_engagement_time();
+ base::Time rebase_score_time = rebase_time - offset;
+ score.set_last_engagement_time(rebase_score_time);
+ }
+
+ if (score.last_engagement_time() > new_last_engagement_time)
+ new_last_engagement_time = score.last_engagement_time();
score.Commit();
}
@@ -468,13 +490,15 @@ void SiteEngagementService::HandleUserInput(
}
bool SiteEngagementService::IsLastEngagementStale() const {
- // This only happens when Chrome is first run and the user has never recorded
- // any engagement.
+ // Only happens on first run when no engagement has ever been recorded.
base::Time last_engagement_time = GetLastEngagementTime();
if (last_engagement_time.is_null())
return false;
- return (clock_->Now() - last_engagement_time) >= GetStalePeriod();
+ // Stale is either too *far* back, or any amount *forward* in time. This could
+ // occur due to a changed clock, or extended non-use of the browser.
+ return (clock_->Now() - last_engagement_time) >= GetStalePeriod() ||
+ (clock_->Now() < last_engagement_time);
}
void SiteEngagementService::OnURLsDeleted(
« no previous file with comments | « chrome/browser/engagement/site_engagement_service.h ('k') | chrome/browser/engagement/site_engagement_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698