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

Side by Side Diff: chrome/browser/engagement/site_engagement_service.cc

Issue 1901563002: Set site engagement timestamps to privacy-respectful values when history is cleared. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 8 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 unified diff | Download patch
OLDNEW
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 <cmath> 10 #include <cmath>
(...skipping 18 matching lines...) Expand all
29 #include "chrome/common/chrome_switches.h" 29 #include "chrome/common/chrome_switches.h"
30 #include "components/content_settings/core/browser/host_content_settings_map.h" 30 #include "components/content_settings/core/browser/host_content_settings_map.h"
31 #include "components/content_settings/core/common/content_settings_pattern.h" 31 #include "components/content_settings/core/common/content_settings_pattern.h"
32 #include "components/history/core/browser/history_service.h" 32 #include "components/history/core/browser/history_service.h"
33 #include "components/variations/variations_associated_data.h" 33 #include "components/variations/variations_associated_data.h"
34 #include "content/public/browser/browser_thread.h" 34 #include "content/public/browser/browser_thread.h"
35 #include "url/gurl.h" 35 #include "url/gurl.h"
36 36
37 namespace { 37 namespace {
38 38
39 const int FOUR_WEEKS_IN_DAYS = 28;
40
39 // Global bool to ensure we only update the parameters from variations once. 41 // Global bool to ensure we only update the parameters from variations once.
40 bool g_updated_from_variations = false; 42 bool g_updated_from_variations = false;
41 43
42 // Keys used in the variations params. Order matches 44 // Keys used in the variations params. Order matches
43 // SiteEngagementScore::Variation enum. 45 // SiteEngagementScore::Variation enum.
44 const char* kVariationNames[] = { 46 const char* kVariationNames[] = {
45 "max_points_per_day", 47 "max_points_per_day",
46 "decay_period_in_days", 48 "decay_period_in_days",
47 "decay_points", 49 "decay_points",
48 "navigation_points", 50 "navigation_points",
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 double to_add = std::min(kMaxPoints - raw_score_, 264 double to_add = std::min(kMaxPoints - raw_score_,
263 GetMaxPointsPerDay() - points_added_today_); 265 GetMaxPointsPerDay() - points_added_today_);
264 to_add = std::min(to_add, points); 266 to_add = std::min(to_add, points);
265 267
266 points_added_today_ += to_add; 268 points_added_today_ += to_add;
267 raw_score_ += to_add; 269 raw_score_ += to_add;
268 270
269 last_engagement_time_ = now; 271 last_engagement_time_ = now;
270 } 272 }
271 273
272 void SiteEngagementScore::Reset(double points) { 274 void SiteEngagementScore::Reset(double points, const base::Time* updated_time) {
273 raw_score_ = points; 275 raw_score_ = points;
274 points_added_today_ = 0; 276 points_added_today_ = 0;
275 277
276 // This must be set in order to prevent the score from decaying when read. 278 // This must be set in order to prevent the score from decaying when read.
277 last_engagement_time_ = clock_->Now(); 279 if (updated_time) {
280 last_engagement_time_ = *updated_time;
281 if (!last_shortcut_launch_time_.is_null())
282 last_shortcut_launch_time_ = *updated_time;
283 } else {
284 last_engagement_time_ = clock_->Now();
285 }
278 } 286 }
279 287
280 bool SiteEngagementScore::MaxPointsPerDayAdded() const { 288 bool SiteEngagementScore::MaxPointsPerDayAdded() const {
281 if (!last_engagement_time_.is_null() && 289 if (!last_engagement_time_.is_null() &&
282 clock_->Now().LocalMidnight() != last_engagement_time_.LocalMidnight()) { 290 clock_->Now().LocalMidnight() != last_engagement_time_.LocalMidnight()) {
283 return false; 291 return false;
284 } 292 }
285 293
286 return points_added_today_ == GetMaxPointsPerDay(); 294 return points_added_today_ == GetMaxPointsPerDay();
287 } 295 }
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 bool is_hidden) { 448 bool is_hidden) {
441 SiteEngagementMetrics::RecordEngagement( 449 SiteEngagementMetrics::RecordEngagement(
442 is_hidden ? SiteEngagementMetrics::ENGAGEMENT_MEDIA_HIDDEN 450 is_hidden ? SiteEngagementMetrics::ENGAGEMENT_MEDIA_HIDDEN
443 : SiteEngagementMetrics::ENGAGEMENT_MEDIA_VISIBLE); 451 : SiteEngagementMetrics::ENGAGEMENT_MEDIA_VISIBLE);
444 AddPoints(url, is_hidden ? SiteEngagementScore::GetHiddenMediaPoints() 452 AddPoints(url, is_hidden ? SiteEngagementScore::GetHiddenMediaPoints()
445 : SiteEngagementScore::GetVisibleMediaPoints()); 453 : SiteEngagementScore::GetVisibleMediaPoints());
446 RecordMetrics(); 454 RecordMetrics();
447 } 455 }
448 456
449 void SiteEngagementService::ResetScoreForURL(const GURL& url, double score) { 457 void SiteEngagementService::ResetScoreForURL(const GURL& url, double score) {
450 DCHECK(url.is_valid()); 458 ResetScoreAndAccessTimesForURL(url, score, nullptr);
451 DCHECK_GE(score, 0);
452 DCHECK_LE(score, SiteEngagementScore::kMaxPoints);
453
454 HostContentSettingsMap* settings_map =
455 HostContentSettingsMapFactory::GetForProfile(profile_);
456 std::unique_ptr<base::DictionaryValue> score_dict =
457 GetScoreDictForOrigin(settings_map, url);
458 SiteEngagementScore engagement_score(clock_.get(), *score_dict);
459
460 engagement_score.Reset(score);
461 if (score == 0) {
462 settings_map->SetWebsiteSettingDefaultScope(
463 url, GURL(), CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(),
464 nullptr);
465 return;
466 }
467
468 if (engagement_score.UpdateScoreDict(score_dict.get())) {
469 settings_map->SetWebsiteSettingDefaultScope(
470 url, GURL(), CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(),
471 score_dict.release());
472 }
473 } 459 }
474 460
475 void SiteEngagementService::OnURLsDeleted( 461 void SiteEngagementService::OnURLsDeleted(
476 history::HistoryService* history_service, 462 history::HistoryService* history_service,
477 bool all_history, 463 bool all_history,
478 bool expired, 464 bool expired,
479 const history::URLRows& deleted_rows, 465 const history::URLRows& deleted_rows,
480 const std::set<GURL>& favicon_urls) { 466 const std::set<GURL>& favicon_urls) {
481 std::multiset<GURL> origins; 467 std::multiset<GURL> origins;
482 for (const history::URLRow& row : deleted_rows) 468 for (const history::URLRow& row : deleted_rows)
483 origins.insert(row.url().GetOrigin()); 469 origins.insert(row.url().GetOrigin());
484 470
485 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( 471 history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
486 profile_, ServiceAccessType::EXPLICIT_ACCESS); 472 profile_, ServiceAccessType::EXPLICIT_ACCESS);
487 hs->GetCountsForOrigins( 473 hs->GetCountsAndLastVisitForOrigins(
488 std::set<GURL>(origins.begin(), origins.end()), 474 std::set<GURL>(origins.begin(), origins.end()),
489 base::Bind(&SiteEngagementService::GetCountsForOriginsComplete, 475 base::Bind(
490 weak_factory_.GetWeakPtr(), origins, expired)); 476 &SiteEngagementService::GetCountsAndLastVisitForOriginsComplete,
477 weak_factory_.GetWeakPtr(), hs, origins, expired));
491 } 478 }
492 479
493 void SiteEngagementService::SetLastShortcutLaunchTime(const GURL& url) { 480 void SiteEngagementService::SetLastShortcutLaunchTime(const GURL& url) {
494 HostContentSettingsMap* settings_map = 481 HostContentSettingsMap* settings_map =
495 HostContentSettingsMapFactory::GetForProfile(profile_); 482 HostContentSettingsMapFactory::GetForProfile(profile_);
496 std::unique_ptr<base::DictionaryValue> score_dict = 483 std::unique_ptr<base::DictionaryValue> score_dict =
497 GetScoreDictForOrigin(settings_map, url); 484 GetScoreDictForOrigin(settings_map, url);
498 SiteEngagementScore score(clock_.get(), *score_dict); 485 SiteEngagementScore score(clock_.get(), *score_dict);
499 486
500 // Record the number of days since the last launch in UMA. If the user's clock 487 // Record the number of days since the last launch in UMA. If the user's clock
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 const std::map<GURL, double>& score_map) const { 725 const std::map<GURL, double>& score_map) const {
739 int total_origins = 0; 726 int total_origins = 0;
740 727
741 for (const auto& value : score_map) 728 for (const auto& value : score_map)
742 if (value.second == SiteEngagementScore::kMaxPoints) 729 if (value.second == SiteEngagementScore::kMaxPoints)
743 ++total_origins; 730 ++total_origins;
744 731
745 return total_origins; 732 return total_origins;
746 } 733 }
747 734
748 void SiteEngagementService::GetCountsForOriginsComplete( 735 void SiteEngagementService::GetCountsAndLastVisitForOriginsComplete(
736 history::HistoryService* history_service,
749 const std::multiset<GURL>& deleted_origins, 737 const std::multiset<GURL>& deleted_origins,
750 bool expired, 738 bool expired,
751 const history::OriginCountMap& remaining_origins) { 739 const history::OriginCountMap& remaining_origins) {
740
741 // The most in-the-past option in the Clear Browsing Dialog aside from "all
742 // time" is 4 weeks ago. Set the last updated date to 4 weeks ago for origins
743 // where we can't find a valid last visit date.
744 base::Time now = clock_->Now();
745 base::Time four_weeks_ago =
746 now - base::TimeDelta::FromDays(FOUR_WEEKS_IN_DAYS);
747
752 for (const auto& origin_to_count : remaining_origins) { 748 for (const auto& origin_to_count : remaining_origins) {
753 GURL origin = origin_to_count.first; 749 GURL origin = origin_to_count.first;
754 int remaining = origin_to_count.second; 750 int remaining = origin_to_count.second.first;
751 base::Time last_visit = origin_to_count.second.second;
755 int deleted = deleted_origins.count(origin); 752 int deleted = deleted_origins.count(origin);
756 753
757 // Do not update engagement scores if the deletion was an expiry, but the 754 // Do not update engagement scores if the deletion was an expiry, but the
758 // URL still has entries in history. 755 // URL still has entries in history.
759 if ((expired && remaining != 0) || deleted == 0) 756 if ((expired && remaining != 0) || deleted == 0)
760 continue; 757 continue;
761 758
759 if (last_visit.is_null() || last_visit > now)
760 last_visit = four_weeks_ago;
761
762 // At this point, we are going to proportionally decay the origin's
763 // engagement, and reset its last visit date to the last visit to a URL
764 // under the origin in history. If this new last visit date is long enough
765 // in the past, the next time the origin's engagement is accessed the
766 // automatic decay will kick in - i.e. a double decay will have occurred.
767 // To prevent this, compute the decay that would have taken place since the
768 // new last visit and add it to the engagement at this point. When the
769 // engagement is next accessed, it will decay back to the proportionally
770 // reduced value rather than being decayed once here, and then once again
771 // when it is next accessed.
772 int undecay = 0;
773 int days_since_engagement = (now - last_visit).InDays();
774 if (days_since_engagement > 0) {
775 int periods = days_since_engagement /
776 SiteEngagementScore::GetDecayPeriodInDays();
777 undecay = periods * SiteEngagementScore::GetDecayPoints();
778 }
779
762 // Remove engagement proportional to the urls expired from the origin's 780 // Remove engagement proportional to the urls expired from the origin's
763 // entire history. 781 // entire history.
764 double proportion_remaining = 782 double proportion_remaining =
765 static_cast<double>(remaining) / (remaining + deleted); 783 static_cast<double>(remaining) / (remaining + deleted);
benwells 2016/04/19 07:28:19 Nit: move proportion_remaining calculation up to l
dominickn 2016/04/19 07:59:32 Done.
766 ResetScoreForURL(origin, proportion_remaining * GetScore(origin)); 784 ResetScoreAndAccessTimesForURL(
785 origin, (proportion_remaining * GetScore(origin)) + undecay,
786 &last_visit);
767 } 787 }
768 } 788 }
789
790 void SiteEngagementService::ResetScoreAndAccessTimesForURL(
791 const GURL& url, double score, const base::Time* updated_time) {
792 DCHECK(url.is_valid());
793 DCHECK_GE(score, 0);
794 DCHECK_LE(score, SiteEngagementScore::kMaxPoints);
benwells 2016/04/19 07:28:19 Should it be impossible for this DCHECK to fire? I
dominickn 2016/04/19 07:59:32 Good point. Done.
795
796 HostContentSettingsMap* settings_map =
797 HostContentSettingsMapFactory::GetForProfile(profile_);
798 std::unique_ptr<base::DictionaryValue> score_dict =
799 GetScoreDictForOrigin(settings_map, url);
800 SiteEngagementScore engagement_score(clock_.get(), *score_dict);
801
802 engagement_score.Reset(score, updated_time);
803 if (score == 0) {
804 settings_map->SetWebsiteSettingDefaultScope(
805 url, GURL(), CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(),
806 nullptr);
807 return;
808 }
809
810 if (engagement_score.UpdateScoreDict(score_dict.get())) {
811 settings_map->SetWebsiteSettingDefaultScope(
812 url, GURL(), CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT, std::string(),
813 score_dict.release());
814 }
815 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698