Chromium Code Reviews| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/time/clock.h" | 11 #include "base/time/clock.h" |
| 12 #include "base/time/default_clock.h" | 12 #include "base/time/default_clock.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 15 #include "chrome/browser/engagement/site_engagement_helper.h" | 15 #include "chrome/browser/engagement/site_engagement_helper.h" |
| 16 #include "chrome/browser/engagement/site_engagement_service_factory.h" | 16 #include "chrome/browser/engagement/site_engagement_service_factory.h" |
| 17 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
| 18 #include "components/content_settings/core/browser/host_content_settings_map.h" | 18 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 19 #include "components/content_settings/core/common/content_settings_pattern.h" | 19 #include "components/content_settings/core/common/content_settings_pattern.h" |
| 20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 21 #include "url/gurl.h" | 21 #include "url/gurl.h" |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 // Length of time between metrics logging. | |
| 26 const base::TimeDelta metrics_interval = base::TimeDelta::FromMinutes(60); | |
| 27 | |
| 25 // Delta within which to consider scores equal. | 28 // Delta within which to consider scores equal. |
| 26 const double kScoreDelta = 0.001; | 29 const double kScoreDelta = 0.001; |
| 27 | 30 |
| 28 // Delta within which to consider internal time values equal. Internal time | 31 // Delta within which to consider internal time values equal. Internal time |
| 29 // values are in microseconds, so this delta comes out at one second. | 32 // values are in microseconds, so this delta comes out at one second. |
| 30 const double kTimeDelta = 1000000; | 33 const double kTimeDelta = 1000000; |
| 31 | 34 |
| 32 scoped_ptr<ContentSettingsForOneType> GetEngagementContentSettings( | 35 scoped_ptr<ContentSettingsForOneType> GetEngagementContentSettings( |
| 33 HostContentSettingsMap* settings_map) { | 36 HostContentSettingsMap* settings_map) { |
| 34 scoped_ptr<ContentSettingsForOneType> engagement_settings( | 37 scoped_ptr<ContentSettingsForOneType> engagement_settings( |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 double to_add = | 109 double to_add = |
| 107 std::min(kMaxPoints - raw_score_, kMaxPointsPerDay - points_added_today_); | 110 std::min(kMaxPoints - raw_score_, kMaxPointsPerDay - points_added_today_); |
| 108 to_add = std::min(to_add, points); | 111 to_add = std::min(to_add, points); |
| 109 | 112 |
| 110 points_added_today_ += to_add; | 113 points_added_today_ += to_add; |
| 111 raw_score_ += to_add; | 114 raw_score_ += to_add; |
| 112 | 115 |
| 113 last_engagement_time_ = now; | 116 last_engagement_time_ = now; |
| 114 } | 117 } |
| 115 | 118 |
| 119 bool SiteEngagementScore::MaxPointsPerDayAdded() { | |
| 120 if (!last_engagement_time_.is_null() && | |
| 121 clock_->Now().LocalMidnight() != last_engagement_time_.LocalMidnight()) { | |
| 122 return false; | |
| 123 } | |
| 124 | |
| 125 return points_added_today_ == kMaxPointsPerDay; | |
| 126 } | |
| 127 | |
| 116 bool SiteEngagementScore::UpdateScoreDict(base::DictionaryValue* score_dict) { | 128 bool SiteEngagementScore::UpdateScoreDict(base::DictionaryValue* score_dict) { |
| 117 double raw_score_orig = 0; | 129 double raw_score_orig = 0; |
| 118 double points_added_today_orig = 0; | 130 double points_added_today_orig = 0; |
| 119 double last_engagement_time_internal_orig = 0; | 131 double last_engagement_time_internal_orig = 0; |
| 120 | 132 |
| 121 score_dict->GetDouble(kRawScoreKey, &raw_score_orig); | 133 score_dict->GetDouble(kRawScoreKey, &raw_score_orig); |
| 122 score_dict->GetDouble(kPointsAddedTodayKey, &points_added_today_orig); | 134 score_dict->GetDouble(kPointsAddedTodayKey, &points_added_today_orig); |
| 123 score_dict->GetDouble(kLastEngagementTimeKey, | 135 score_dict->GetDouble(kLastEngagementTimeKey, |
| 124 &last_engagement_time_internal_orig); | 136 &last_engagement_time_internal_orig); |
| 125 bool changed = | 137 bool changed = |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 bool SiteEngagementService::IsEnabled() { | 182 bool SiteEngagementService::IsEnabled() { |
| 171 return base::CommandLine::ForCurrentProcess()->HasSwitch( | 183 return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 172 switches::kEnableSiteEngagementService); | 184 switches::kEnableSiteEngagementService); |
| 173 } | 185 } |
| 174 | 186 |
| 175 SiteEngagementService::SiteEngagementService(Profile* profile) | 187 SiteEngagementService::SiteEngagementService(Profile* profile) |
| 176 : SiteEngagementService(profile, make_scoped_ptr(new base::DefaultClock)) { | 188 : SiteEngagementService(profile, make_scoped_ptr(new base::DefaultClock)) { |
| 177 content::BrowserThread::PostAfterStartupTask( | 189 content::BrowserThread::PostAfterStartupTask( |
| 178 FROM_HERE, content::BrowserThread::GetMessageLoopProxyForThread( | 190 FROM_HERE, content::BrowserThread::GetMessageLoopProxyForThread( |
| 179 content::BrowserThread::UI), | 191 content::BrowserThread::UI), |
| 180 base::Bind(&SiteEngagementService::CleanupEngagementScores, | 192 base::Bind(&SiteEngagementService::AfterStartupTask, |
| 181 weak_factory_.GetWeakPtr())); | 193 weak_factory_.GetWeakPtr())); |
| 182 } | 194 } |
| 183 | 195 |
| 184 SiteEngagementService::~SiteEngagementService() { | 196 SiteEngagementService::~SiteEngagementService() { |
| 185 } | 197 } |
| 186 | 198 |
| 187 void SiteEngagementService::HandleNavigation(const GURL& url, | 199 void SiteEngagementService::HandleNavigation(const GURL& url, |
| 188 ui::PageTransition transition) { | 200 ui::PageTransition transition) { |
| 201 SiteEngagementMetrics::RecordEngagement( | |
| 202 SiteEngagementMetrics::ENGAGEMENT_NAVIGATION); | |
| 189 AddPoints(url, SiteEngagementScore::kNavigationPoints); | 203 AddPoints(url, SiteEngagementScore::kNavigationPoints); |
| 204 | |
| 205 if (clock_->Now() - last_metrics_time_ >= metrics_interval) | |
| 206 RecordMetrics(); | |
| 190 } | 207 } |
| 191 | 208 |
| 192 void SiteEngagementService::HandleUserInput(const GURL& url) { | 209 void SiteEngagementService::HandleUserInput( |
| 210 const GURL& url, | |
| 211 SiteEngagementMetrics::EngagementType type) { | |
| 212 SiteEngagementMetrics::RecordEngagement(type); | |
| 193 AddPoints(url, SiteEngagementScore::kUserInputPoints); | 213 AddPoints(url, SiteEngagementScore::kUserInputPoints); |
| 214 | |
| 215 if (clock_->Now() - last_metrics_time_ >= metrics_interval) | |
|
benwells
2015/10/02 01:33:25
This could happen before the startup stuff. You sh
dominickn
2015/10/02 04:54:50
Done.
| |
| 216 RecordMetrics(); | |
| 194 } | 217 } |
| 195 | 218 |
| 196 double SiteEngagementService::GetScore(const GURL& url) { | 219 double SiteEngagementService::GetScore(const GURL& url) { |
| 197 HostContentSettingsMap* settings_map = | 220 HostContentSettingsMap* settings_map = |
| 198 HostContentSettingsMapFactory::GetForProfile(profile_); | 221 HostContentSettingsMapFactory::GetForProfile(profile_); |
| 199 scoped_ptr<base::DictionaryValue> score_dict = | 222 scoped_ptr<base::DictionaryValue> score_dict = |
| 200 GetScoreDictForOrigin(settings_map, url); | 223 GetScoreDictForOrigin(settings_map, url); |
| 201 SiteEngagementScore score(clock_.get(), *score_dict); | 224 SiteEngagementScore score(clock_.get(), *score_dict); |
| 202 | 225 |
| 203 return score.Score(); | 226 return score.Score(); |
| 204 } | 227 } |
| 205 | 228 |
| 206 double SiteEngagementService::GetTotalEngagementPoints() { | 229 double SiteEngagementService::GetTotalEngagementPoints() { |
| 207 HostContentSettingsMap* settings_map = | 230 std::map<GURL, double> score_map = GetScoreMap(); |
| 208 HostContentSettingsMapFactory::GetForProfile(profile_); | |
| 209 scoped_ptr<ContentSettingsForOneType> engagement_settings = | |
| 210 GetEngagementContentSettings(settings_map); | |
| 211 | 231 |
| 212 double total_score = 0; | 232 double total_score = 0; |
| 213 for (const auto& site : *engagement_settings) { | 233 for (const auto& value : score_map) |
| 214 GURL origin(site.primary_pattern.ToString()); | 234 total_score += value.second; |
| 215 if (!origin.is_valid()) | |
| 216 continue; | |
| 217 | 235 |
| 218 scoped_ptr<base::DictionaryValue> score_dict = | |
| 219 GetScoreDictForOrigin(settings_map, origin); | |
| 220 SiteEngagementScore score(clock_.get(), *score_dict); | |
| 221 total_score += score.Score(); | |
| 222 } | |
| 223 return total_score; | 236 return total_score; |
| 224 } | 237 } |
| 225 | 238 |
| 226 std::map<GURL, double> SiteEngagementService::GetScoreMap() { | 239 std::map<GURL, double> SiteEngagementService::GetScoreMap() { |
| 227 HostContentSettingsMap* settings_map = | 240 HostContentSettingsMap* settings_map = |
| 228 HostContentSettingsMapFactory::GetForProfile(profile_); | 241 HostContentSettingsMapFactory::GetForProfile(profile_); |
| 229 scoped_ptr<ContentSettingsForOneType> engagement_settings = | 242 scoped_ptr<ContentSettingsForOneType> engagement_settings = |
| 230 GetEngagementContentSettings(settings_map); | 243 GetEngagementContentSettings(settings_map); |
| 231 | 244 |
| 232 std::map<GURL, double> score_map; | 245 std::map<GURL, double> score_map; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 261 ContentSettingsPattern::FromURLNoWildcard(url)); | 274 ContentSettingsPattern::FromURLNoWildcard(url)); |
| 262 if (!pattern.IsValid()) | 275 if (!pattern.IsValid()) |
| 263 return; | 276 return; |
| 264 | 277 |
| 265 settings_map->SetWebsiteSetting(pattern, ContentSettingsPattern::Wildcard(), | 278 settings_map->SetWebsiteSetting(pattern, ContentSettingsPattern::Wildcard(), |
| 266 CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, | 279 CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, |
| 267 std::string(), score_dict.release()); | 280 std::string(), score_dict.release()); |
| 268 } | 281 } |
| 269 } | 282 } |
| 270 | 283 |
| 284 void SiteEngagementService::AfterStartupTask() { | |
| 285 CleanupEngagementScores(); | |
| 286 RecordMetrics(); | |
| 287 } | |
| 288 | |
| 271 void SiteEngagementService::CleanupEngagementScores() { | 289 void SiteEngagementService::CleanupEngagementScores() { |
| 272 HostContentSettingsMap* settings_map = | 290 HostContentSettingsMap* settings_map = |
| 273 HostContentSettingsMapFactory::GetForProfile(profile_); | 291 HostContentSettingsMapFactory::GetForProfile(profile_); |
| 274 scoped_ptr<ContentSettingsForOneType> engagement_settings = | 292 scoped_ptr<ContentSettingsForOneType> engagement_settings = |
| 275 GetEngagementContentSettings(settings_map); | 293 GetEngagementContentSettings(settings_map); |
| 276 | 294 |
| 277 for (const auto& site : *engagement_settings) { | 295 for (const auto& site : *engagement_settings) { |
| 278 GURL origin(site.primary_pattern.ToString()); | 296 GURL origin(site.primary_pattern.ToString()); |
| 279 if (origin.is_valid()) { | 297 if (origin.is_valid()) { |
| 280 scoped_ptr<base::DictionaryValue> score_dict = | 298 scoped_ptr<base::DictionaryValue> score_dict = |
| 281 GetScoreDictForOrigin(settings_map, origin); | 299 GetScoreDictForOrigin(settings_map, origin); |
| 282 SiteEngagementScore score(clock_.get(), *score_dict); | 300 SiteEngagementScore score(clock_.get(), *score_dict); |
| 283 if (score.Score() != 0) | 301 if (score.Score() != 0) |
| 284 continue; | 302 continue; |
| 285 } | 303 } |
| 286 | 304 |
| 287 settings_map->SetWebsiteSetting( | 305 settings_map->SetWebsiteSetting( |
| 288 site.primary_pattern, ContentSettingsPattern::Wildcard(), | 306 site.primary_pattern, ContentSettingsPattern::Wildcard(), |
| 289 CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(), nullptr); | 307 CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(), nullptr); |
| 290 } | 308 } |
| 291 } | 309 } |
| 292 | 310 |
| 311 int SiteEngagementService::OriginsWithMaxDailyEngagement() { | |
| 312 HostContentSettingsMap* settings_map = | |
| 313 HostContentSettingsMapFactory::GetForProfile(profile_); | |
| 314 scoped_ptr<ContentSettingsForOneType> engagement_settings = | |
| 315 GetEngagementContentSettings(settings_map); | |
| 316 | |
| 317 int total_origins = 0; | |
| 318 | |
| 319 // We cannot call GetScoreMap as we need the score objects, not raw scores. | |
| 320 for (const auto& site : *engagement_settings) { | |
| 321 GURL origin(site.primary_pattern.ToString()); | |
| 322 if (!origin.is_valid()) | |
| 323 continue; | |
| 324 | |
| 325 scoped_ptr<base::DictionaryValue> score_dict = | |
| 326 GetScoreDictForOrigin(settings_map, origin); | |
| 327 SiteEngagementScore score(clock_.get(), *score_dict); | |
| 328 if (score.MaxPointsPerDayAdded()) | |
| 329 total_origins += 1; | |
|
calamity
2015/10/02 03:46:29
nit: ++total_origins
dominickn
2015/10/02 04:54:50
Done.
| |
| 330 } | |
| 331 | |
| 332 return total_origins; | |
| 333 } | |
| 334 | |
| 335 int SiteEngagementService::OriginsWithMaxEngagement( | |
| 336 std::map<GURL, double>& score_map) { | |
| 337 int total_origins = 0; | |
| 338 | |
| 339 for (const auto& value : score_map) | |
| 340 if (value.second == SiteEngagementScore::kMaxPoints) | |
| 341 ++total_origins; | |
| 342 | |
| 343 return total_origins; | |
| 344 } | |
| 345 | |
| 346 void SiteEngagementService::RecordMetrics() { | |
| 347 last_metrics_time_ = clock_->Now(); | |
| 348 std::map<GURL, double> score_map = GetScoreMap(); | |
| 349 | |
| 350 int origins_with_max_engagement = OriginsWithMaxEngagement(score_map); | |
| 351 int total_origins = score_map.size(); | |
| 352 int percent_origins_with_max_engagement = | |
| 353 (total_origins == 0 ? 0 : (origins_with_max_engagement * 100) / | |
| 354 total_origins); | |
| 355 | |
| 356 double total_engagement = GetTotalEngagementPoints(); | |
| 357 double average_engagement = | |
| 358 (total_origins == 0 ? 0 : total_engagement / total_origins); | |
| 359 | |
| 360 SiteEngagementMetrics::RecordTotalOriginsEngaged(total_origins); | |
| 361 SiteEngagementMetrics::RecordTotalSiteEngagement(total_engagement); | |
| 362 SiteEngagementMetrics::RecordAverageEngagement(average_engagement); | |
| 363 SiteEngagementMetrics::RecordEngagementScores(score_map); | |
| 364 | |
| 365 SiteEngagementMetrics::RecordOriginsWithMaxDailyEngagement( | |
| 366 OriginsWithMaxDailyEngagement()); | |
| 367 SiteEngagementMetrics::RecordOriginsWithMaxEngagement( | |
| 368 origins_with_max_engagement); | |
| 369 SiteEngagementMetrics::RecordPercentOriginsWithMaxEngagement( | |
| 370 percent_origins_with_max_engagement); | |
| 371 } | |
| OLD | NEW |