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 <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <utility> | 10 #include <utility> |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 } | 160 } |
161 | 161 |
162 return score_map; | 162 return score_map; |
163 } | 163 } |
164 | 164 |
165 bool SiteEngagementService::IsBootstrapped() const { | 165 bool SiteEngagementService::IsBootstrapped() const { |
166 return GetTotalEngagementPoints() >= | 166 return GetTotalEngagementPoints() >= |
167 SiteEngagementScore::GetBootstrapPoints(); | 167 SiteEngagementScore::GetBootstrapPoints(); |
168 } | 168 } |
169 | 169 |
170 bool SiteEngagementService::IsEngagementAtLeast( | 170 bool SiteEngagementService::IsEngagementAtLeast(const GURL& url, |
171 const GURL& url, | 171 EngagementLevel level) const { |
172 EngagementLevel level) const { | |
173 DCHECK_LT(SiteEngagementScore::GetMediumEngagementBoundary(), | 172 DCHECK_LT(SiteEngagementScore::GetMediumEngagementBoundary(), |
174 SiteEngagementScore::GetHighEngagementBoundary()); | 173 SiteEngagementScore::GetHighEngagementBoundary()); |
175 double score = GetScore(url); | 174 double score = GetScore(url); |
176 switch (level) { | 175 switch (level) { |
177 case ENGAGEMENT_LEVEL_NONE: | 176 case ENGAGEMENT_LEVEL_NONE: |
178 return true; | 177 return true; |
179 case ENGAGEMENT_LEVEL_LOW: | 178 case ENGAGEMENT_LEVEL_LOW: |
180 return score > 0; | 179 return score > 0; |
181 case ENGAGEMENT_LEVEL_MEDIUM: | 180 case ENGAGEMENT_LEVEL_MEDIUM: |
182 return score >= SiteEngagementScore::GetMediumEngagementBoundary(); | 181 return score >= SiteEngagementScore::GetMediumEngagementBoundary(); |
183 case ENGAGEMENT_LEVEL_HIGH: | 182 case ENGAGEMENT_LEVEL_HIGH: |
184 return score >= SiteEngagementScore::GetHighEngagementBoundary(); | 183 return score >= SiteEngagementScore::GetHighEngagementBoundary(); |
185 case ENGAGEMENT_LEVEL_MAX: | 184 case ENGAGEMENT_LEVEL_MAX: |
186 return score == SiteEngagementScore::kMaxPoints; | 185 return score == SiteEngagementScore::kMaxPoints; |
187 } | 186 } |
188 NOTREACHED(); | 187 NOTREACHED(); |
189 return false; | 188 return false; |
190 } | 189 } |
191 | 190 |
| 191 void SiteEngagementService::AddObserver(SiteEngagementObserver* observer) { |
| 192 observer_list_.AddObserver(observer); |
| 193 } |
| 194 |
| 195 void SiteEngagementService::RemoveObserver(SiteEngagementObserver* observer) { |
| 196 observer_list_.RemoveObserver(observer); |
| 197 } |
| 198 |
192 void SiteEngagementService::ResetScoreForURL(const GURL& url, double score) { | 199 void SiteEngagementService::ResetScoreForURL(const GURL& url, double score) { |
193 SiteEngagementScore engagement_score = CreateEngagementScore(url); | 200 SiteEngagementScore engagement_score = CreateEngagementScore(url); |
194 engagement_score.Reset(score, clock_->Now()); | 201 engagement_score.Reset(score, clock_->Now()); |
195 engagement_score.Commit(); | 202 engagement_score.Commit(); |
196 } | 203 } |
197 | 204 |
198 void SiteEngagementService::SetLastShortcutLaunchTime(const GURL& url) { | 205 void SiteEngagementService::SetLastShortcutLaunchTime(const GURL& url) { |
199 SiteEngagementScore score = CreateEngagementScore(url); | 206 SiteEngagementScore score = CreateEngagementScore(url); |
200 | 207 |
201 // Record the number of days since the last launch in UMA. If the user's clock | 208 // Record the number of days since the last launch in UMA. If the user's clock |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 score.Commit(); | 251 score.Commit(); |
245 } | 252 } |
246 | 253 |
247 void SiteEngagementService::AfterStartupTask() { | 254 void SiteEngagementService::AfterStartupTask() { |
248 CleanupEngagementScores(); | 255 CleanupEngagementScores(); |
249 RecordMetrics(); | 256 RecordMetrics(); |
250 } | 257 } |
251 | 258 |
252 void SiteEngagementService::CleanupEngagementScores() { | 259 void SiteEngagementService::CleanupEngagementScores() { |
253 HostContentSettingsMap* settings_map = | 260 HostContentSettingsMap* settings_map = |
254 HostContentSettingsMapFactory::GetForProfile(profile_); | 261 HostContentSettingsMapFactory::GetForProfile(profile_); |
255 std::unique_ptr<ContentSettingsForOneType> engagement_settings = | 262 std::unique_ptr<ContentSettingsForOneType> engagement_settings = |
256 GetEngagementContentSettings(settings_map); | 263 GetEngagementContentSettings(settings_map); |
257 | 264 |
258 for (const auto& site : *engagement_settings) { | 265 for (const auto& site : *engagement_settings) { |
259 GURL origin(site.primary_pattern.ToString()); | 266 GURL origin(site.primary_pattern.ToString()); |
260 if (origin.is_valid() && GetScore(origin) != 0) | 267 if (origin.is_valid() && GetScore(origin) != 0) |
261 continue; | 268 continue; |
262 | 269 |
263 settings_map->SetWebsiteSettingDefaultScope( | 270 settings_map->SetWebsiteSettingDefaultScope( |
264 origin, GURL(), CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(), | 271 origin, GURL(), CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(), |
265 nullptr); | 272 nullptr); |
266 } | 273 } |
267 } | 274 } |
268 | 275 |
269 void SiteEngagementService::RecordMetrics() { | 276 void SiteEngagementService::RecordMetrics() { |
270 base::Time now = clock_->Now(); | 277 base::Time now = clock_->Now(); |
271 if (last_metrics_time_.is_null() || | 278 if (last_metrics_time_.is_null() || |
272 (now - last_metrics_time_).InMinutes() >= kMetricsIntervalInMinutes) { | 279 (now - last_metrics_time_).InMinutes() >= kMetricsIntervalInMinutes) { |
273 last_metrics_time_ = now; | 280 last_metrics_time_ = now; |
274 std::map<GURL, double> score_map = GetScoreMap(); | 281 std::map<GURL, double> score_map = GetScoreMap(); |
275 | 282 |
276 int origins_with_max_engagement = OriginsWithMaxEngagement(score_map); | 283 int origins_with_max_engagement = OriginsWithMaxEngagement(score_map); |
277 int total_origins = score_map.size(); | 284 int total_origins = score_map.size(); |
278 int percent_origins_with_max_engagement = | 285 int percent_origins_with_max_engagement = |
279 (total_origins == 0 ? 0 : (origins_with_max_engagement * 100) / | 286 (total_origins == 0 |
280 total_origins); | 287 ? 0 |
| 288 : (origins_with_max_engagement * 100) / total_origins); |
281 | 289 |
282 double total_engagement = GetTotalEngagementPoints(); | 290 double total_engagement = GetTotalEngagementPoints(); |
283 double mean_engagement = | 291 double mean_engagement = |
284 (total_origins == 0 ? 0 : total_engagement / total_origins); | 292 (total_origins == 0 ? 0 : total_engagement / total_origins); |
285 | 293 |
286 SiteEngagementMetrics::RecordTotalOriginsEngaged(total_origins); | 294 SiteEngagementMetrics::RecordTotalOriginsEngaged(total_origins); |
287 SiteEngagementMetrics::RecordTotalSiteEngagement(total_engagement); | 295 SiteEngagementMetrics::RecordTotalSiteEngagement(total_engagement); |
288 SiteEngagementMetrics::RecordMeanEngagement(mean_engagement); | 296 SiteEngagementMetrics::RecordMeanEngagement(mean_engagement); |
289 SiteEngagementMetrics::RecordMedianEngagement( | 297 SiteEngagementMetrics::RecordMedianEngagement( |
290 GetMedianEngagement(score_map)); | 298 GetMedianEngagement(score_map)); |
(...skipping 23 matching lines...) Expand all Loading... |
314 // scores otherwise. | 322 // scores otherwise. |
315 std::sort(scores.begin(), scores.end()); | 323 std::sort(scores.begin(), scores.end()); |
316 size_t mid = scores.size() / 2; | 324 size_t mid = scores.size() / 2; |
317 if (scores.size() % 2 == 1) | 325 if (scores.size() % 2 == 1) |
318 return scores[mid]; | 326 return scores[mid]; |
319 else | 327 else |
320 return (scores[mid - 1] + scores[mid]) / 2; | 328 return (scores[mid - 1] + scores[mid]) / 2; |
321 } | 329 } |
322 | 330 |
323 void SiteEngagementService::HandleMediaPlaying( | 331 void SiteEngagementService::HandleMediaPlaying( |
324 content::WebContents* web_contents, bool is_hidden) { | 332 content::WebContents* web_contents, |
| 333 bool is_hidden) { |
| 334 const GURL& url = web_contents->GetVisibleURL(); |
325 SiteEngagementMetrics::RecordEngagement( | 335 SiteEngagementMetrics::RecordEngagement( |
326 is_hidden ? SiteEngagementMetrics::ENGAGEMENT_MEDIA_HIDDEN | 336 is_hidden ? SiteEngagementMetrics::ENGAGEMENT_MEDIA_HIDDEN |
327 : SiteEngagementMetrics::ENGAGEMENT_MEDIA_VISIBLE); | 337 : SiteEngagementMetrics::ENGAGEMENT_MEDIA_VISIBLE); |
328 AddPoints(web_contents->GetVisibleURL(), | 338 AddPoints(url, is_hidden ? SiteEngagementScore::GetHiddenMediaPoints() |
329 is_hidden ? SiteEngagementScore::GetHiddenMediaPoints() | 339 : SiteEngagementScore::GetVisibleMediaPoints()); |
330 : SiteEngagementScore::GetVisibleMediaPoints()); | 340 |
331 RecordMetrics(); | 341 RecordMetrics(); |
| 342 FOR_EACH_OBSERVER( |
| 343 SiteEngagementObserver, observer_list_, |
| 344 OnEngagementIncreased(web_contents, url, GetScore(url))); |
332 } | 345 } |
333 | 346 |
334 void SiteEngagementService::HandleNavigation(content::WebContents* web_contents, | 347 void SiteEngagementService::HandleNavigation(content::WebContents* web_contents, |
335 ui::PageTransition transition) { | 348 ui::PageTransition transition) { |
336 if (IsEngagementNavigation(transition)) { | 349 if (IsEngagementNavigation(transition)) { |
| 350 const GURL& url = web_contents->GetLastCommittedURL(); |
337 SiteEngagementMetrics::RecordEngagement( | 351 SiteEngagementMetrics::RecordEngagement( |
338 SiteEngagementMetrics::ENGAGEMENT_NAVIGATION); | 352 SiteEngagementMetrics::ENGAGEMENT_NAVIGATION); |
339 AddPoints(web_contents->GetLastCommittedURL(), | 353 AddPoints(url, SiteEngagementScore::GetNavigationPoints()); |
340 SiteEngagementScore::GetNavigationPoints()); | 354 |
341 RecordMetrics(); | 355 RecordMetrics(); |
| 356 FOR_EACH_OBSERVER( |
| 357 SiteEngagementObserver, observer_list_, |
| 358 OnEngagementIncreased(web_contents, url, GetScore(url))); |
342 } | 359 } |
343 } | 360 } |
344 | 361 |
345 void SiteEngagementService::HandleUserInput( | 362 void SiteEngagementService::HandleUserInput( |
346 content::WebContents* web_contents, | 363 content::WebContents* web_contents, |
347 SiteEngagementMetrics::EngagementType type) { | 364 SiteEngagementMetrics::EngagementType type) { |
| 365 const GURL& url = web_contents->GetVisibleURL(); |
348 SiteEngagementMetrics::RecordEngagement(type); | 366 SiteEngagementMetrics::RecordEngagement(type); |
349 AddPoints(web_contents->GetVisibleURL(), | 367 AddPoints(url, SiteEngagementScore::GetUserInputPoints()); |
350 SiteEngagementScore::GetUserInputPoints()); | 368 |
351 RecordMetrics(); | 369 RecordMetrics(); |
| 370 FOR_EACH_OBSERVER( |
| 371 SiteEngagementObserver, observer_list_, |
| 372 OnEngagementIncreased(web_contents, url, GetScore(url))); |
352 } | 373 } |
353 | 374 |
354 void SiteEngagementService::OnURLsDeleted( | 375 void SiteEngagementService::OnURLsDeleted( |
355 history::HistoryService* history_service, | 376 history::HistoryService* history_service, |
356 bool all_history, | 377 bool all_history, |
357 bool expired, | 378 bool expired, |
358 const history::URLRows& deleted_rows, | 379 const history::URLRows& deleted_rows, |
359 const std::set<GURL>& favicon_urls) { | 380 const std::set<GURL>& favicon_urls) { |
360 std::multiset<GURL> origins; | 381 std::multiset<GURL> origins; |
361 for (const history::URLRow& row : deleted_rows) | 382 for (const history::URLRow& row : deleted_rows) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 ++total_origins; | 435 ++total_origins; |
415 | 436 |
416 return total_origins; | 437 return total_origins; |
417 } | 438 } |
418 | 439 |
419 void SiteEngagementService::GetCountsAndLastVisitForOriginsComplete( | 440 void SiteEngagementService::GetCountsAndLastVisitForOriginsComplete( |
420 history::HistoryService* history_service, | 441 history::HistoryService* history_service, |
421 const std::multiset<GURL>& deleted_origins, | 442 const std::multiset<GURL>& deleted_origins, |
422 bool expired, | 443 bool expired, |
423 const history::OriginCountAndLastVisitMap& remaining_origins) { | 444 const history::OriginCountAndLastVisitMap& remaining_origins) { |
424 | |
425 // The most in-the-past option in the Clear Browsing Dialog aside from "all | 445 // The most in-the-past option in the Clear Browsing Dialog aside from "all |
426 // time" is 4 weeks ago. Set the last updated date to 4 weeks ago for origins | 446 // time" is 4 weeks ago. Set the last updated date to 4 weeks ago for origins |
427 // where we can't find a valid last visit date. | 447 // where we can't find a valid last visit date. |
428 base::Time now = clock_->Now(); | 448 base::Time now = clock_->Now(); |
429 base::Time four_weeks_ago = | 449 base::Time four_weeks_ago = |
430 now - base::TimeDelta::FromDays(FOUR_WEEKS_IN_DAYS); | 450 now - base::TimeDelta::FromDays(FOUR_WEEKS_IN_DAYS); |
431 | 451 |
432 for (const auto& origin_to_count : remaining_origins) { | 452 for (const auto& origin_to_count : remaining_origins) { |
433 GURL origin = origin_to_count.first; | 453 GURL origin = origin_to_count.first; |
434 // It appears that the history service occasionally sends bad URLs to us. | 454 // It appears that the history service occasionally sends bad URLs to us. |
(...skipping 23 matching lines...) Expand all Loading... |
458 // in the past, the next time the origin's engagement is accessed the | 478 // in the past, the next time the origin's engagement is accessed the |
459 // automatic decay will kick in - i.e. a double decay will have occurred. | 479 // automatic decay will kick in - i.e. a double decay will have occurred. |
460 // To prevent this, compute the decay that would have taken place since the | 480 // To prevent this, compute the decay that would have taken place since the |
461 // new last visit and add it to the engagement at this point. When the | 481 // new last visit and add it to the engagement at this point. When the |
462 // engagement is next accessed, it will decay back to the proportionally | 482 // engagement is next accessed, it will decay back to the proportionally |
463 // reduced value rather than being decayed once here, and then once again | 483 // reduced value rather than being decayed once here, and then once again |
464 // when it is next accessed. | 484 // when it is next accessed. |
465 int undecay = 0; | 485 int undecay = 0; |
466 int days_since_engagement = (now - last_visit).InDays(); | 486 int days_since_engagement = (now - last_visit).InDays(); |
467 if (days_since_engagement > 0) { | 487 if (days_since_engagement > 0) { |
468 int periods = days_since_engagement / | 488 int periods = |
469 SiteEngagementScore::GetDecayPeriodInDays(); | 489 days_since_engagement / SiteEngagementScore::GetDecayPeriodInDays(); |
470 undecay = periods * SiteEngagementScore::GetDecayPoints(); | 490 undecay = periods * SiteEngagementScore::GetDecayPoints(); |
471 } | 491 } |
472 | 492 |
473 SiteEngagementScore engagement_score = CreateEngagementScore(origin); | 493 SiteEngagementScore engagement_score = CreateEngagementScore(origin); |
474 | 494 |
475 double score = std::min( | 495 double score = std::min( |
476 SiteEngagementScore::kMaxPoints, | 496 SiteEngagementScore::kMaxPoints, |
477 (proportion_remaining * engagement_score.GetScore()) + undecay); | 497 (proportion_remaining * engagement_score.GetScore()) + undecay); |
478 engagement_score.Reset(score, last_visit); | 498 engagement_score.Reset(score, last_visit); |
479 if (!engagement_score.last_shortcut_launch_time().is_null() | 499 if (!engagement_score.last_shortcut_launch_time().is_null() && |
480 && engagement_score.last_shortcut_launch_time() > last_visit) { | 500 engagement_score.last_shortcut_launch_time() > last_visit) { |
481 engagement_score.set_last_shortcut_launch_time(last_visit); | 501 engagement_score.set_last_shortcut_launch_time(last_visit); |
482 } | 502 } |
483 | 503 |
484 engagement_score.Commit(); | 504 engagement_score.Commit(); |
485 } | 505 } |
486 } | 506 } |
OLD | NEW |