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 3780227d8785054211d8ef993c99ce054c036b3b..53519c53ed3e30fc4078597da82d1b353cabc4ad 100644 |
--- a/chrome/browser/engagement/site_engagement_service.cc |
+++ b/chrome/browser/engagement/site_engagement_service.cc |
@@ -25,10 +25,13 @@ |
#include "chrome/browser/engagement/site_engagement_score.h" |
#include "chrome/browser/engagement/site_engagement_service_factory.h" |
#include "chrome/browser/history/history_service_factory.h" |
+#include "chrome/browser/profiles/profile.h" |
#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/pref_names.h" |
#include "components/content_settings/core/browser/host_content_settings_map.h" |
#include "components/content_settings/core/common/content_settings_pattern.h" |
#include "components/history/core/browser/history_service.h" |
+#include "components/prefs/pref_service.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/web_contents.h" |
#include "url/gurl.h" |
@@ -118,6 +121,10 @@ SiteEngagementService::SiteEngagementService(Profile* profile) |
} |
SiteEngagementService::~SiteEngagementService() { |
+ // Persist the last engagement time to disk. |
+ profile_->GetPrefs()->SetInt64(prefs::kSiteEngagementLastUpdateTime, |
+ last_engagement_time_.ToInternalValue()); |
+ |
history::HistoryService* history = HistoryServiceFactory::GetForProfile( |
profile_, ServiceAccessType::IMPLICIT_ACCESS); |
if (history) |
@@ -230,6 +237,10 @@ double SiteEngagementService::GetTotalEngagementPoints() const { |
SiteEngagementService::SiteEngagementService(Profile* profile, |
std::unique_ptr<base::Clock> clock) |
: profile_(profile), clock_(std::move(clock)), weak_factory_(this) { |
+ // Read in the last engagement time (or a null time on first run) from disk. |
+ last_engagement_time_ = base::Time::FromInternalValue( |
+ profile->GetPrefs()->GetInt64(prefs::kSiteEngagementLastUpdateTime)); |
+ |
// May be null in tests. |
history::HistoryService* history = HistoryServiceFactory::GetForProfile( |
profile, ServiceAccessType::IMPLICIT_ACCESS); |
@@ -238,32 +249,74 @@ SiteEngagementService::SiteEngagementService(Profile* profile, |
} |
void SiteEngagementService::AddPoints(const GURL& url, double points) { |
- SiteEngagementScore score = CreateEngagementScore(url); |
+ // Trigger a cleanup and date adjustment if it has been a substantial length |
+ // of time since *any* engagement was recorded by the service. This will |
+ // ensure that we do not decay scores when the user did not use the browser. |
+ // IsLastEngagementObsolete is tested separately so that we do not run cleanup |
+ // in this method unless absolutely necessary. |
+ if (IsLastEngagementObsolete()) |
+ CleanupEngagementScores(true); |
+ SiteEngagementScore score = CreateEngagementScore(url); |
score.AddPoints(points); |
score.Commit(); |
+ |
+ last_engagement_time_ = score.last_engagement_time(); |
} |
void SiteEngagementService::AfterStartupTask() { |
- CleanupEngagementScores(); |
+ // Check if we need to reset last engagement times on startup - we want to |
+ // avoid doing this in AddPoints() if possible. It is still necessary to check |
+ // in AddPoints for people who never restart Chrome, but leave it open and |
+ // their computer on standby. |
+ CleanupEngagementScores(IsLastEngagementObsolete()); |
RecordMetrics(); |
} |
-void SiteEngagementService::CleanupEngagementScores() { |
+void SiteEngagementService::CleanupEngagementScores( |
calamity
2016/06/23 05:18:40
It might be worth renaming this method now since i
dominickn
2016/06/27 02:53:35
I think Cleanup is still the right name for the me
|
+ bool update_last_engagement_time) { |
+ // This method should not be called with |update_last_engagement_time| = true |
+ // if the last engagement time isn't obsolete. |
+ DCHECK(!update_last_engagement_time || IsLastEngagementObsolete()); |
+ |
HostContentSettingsMap* settings_map = |
HostContentSettingsMapFactory::GetForProfile(profile_); |
std::unique_ptr<ContentSettingsForOneType> engagement_settings = |
GetEngagementContentSettings(settings_map); |
+ base::Time now = clock_->Now(); |
for (const auto& site : *engagement_settings) { |
GURL origin(site.primary_pattern.ToString()); |
- if (origin.is_valid() && GetScore(origin) != 0) |
+ SiteEngagementScore score = CreateEngagementScore(origin); |
+ |
+ if (origin.is_valid()) { |
+ 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 now - offset to preserve its state, but relative |
+ // to now. |
+ base::TimeDelta offset = |
+ last_engagement_time_ - score.last_engagement_time(); |
+ score.set_last_engagement_time(now - offset); |
calamity
2016/06/23 05:18:40
I think that all scores should be rebased to the o
dominickn
2016/06/27 02:53:35
Done.
|
+ } |
+ |
+ if (score.GetScore() != 0) { |
+ score.Commit(); |
continue; |
+ } |
+ } |
+ // This origin has a score of 0. Wipe it from content settings. |
settings_map->SetWebsiteSettingDefaultScope( |
origin, GURL(), CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(), |
nullptr); |
} |
+ |
+ // Set the last engagement time to now for consistency and to ensure we do not |
+ // double-reset. Persist the time to disk. |
+ last_engagement_time_ = now; |
+ profile_->GetPrefs()->SetInt64(prefs::kSiteEngagementLastUpdateTime, |
+ last_engagement_time_.ToInternalValue()); |
} |
void SiteEngagementService::RecordMetrics() { |
@@ -299,6 +352,19 @@ void SiteEngagementService::RecordMetrics() { |
} |
} |
+bool SiteEngagementService::IsLastEngagementObsolete() { |
+ // This only happens when Chrome is first run and the user has never recorded |
+ // any engagement. |
+ if (last_engagement_time_.is_null()) |
+ return false; |
+ |
+ // Last engagement is obsolete when more than |
+ // OBSOLETE_LAST_ENGAGEMENT_PERIOD_IN_HOURS have passed. |
+ return (clock_->Now() - last_engagement_time_) >= |
+ base::TimeDelta::FromHours( |
+ SiteEngagementScore::GetObsoleteLastEngagementPeriodInHours()); |
+} |
+ |
double SiteEngagementService::GetMedianEngagement( |
const std::map<GURL, double>& score_map) const { |
if (score_map.size() == 0) |