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 |