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> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
15 #include "base/metrics/field_trial.h" | 15 #include "base/metrics/field_trial.h" |
16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
17 #include "base/time/clock.h" | 17 #include "base/time/clock.h" |
18 #include "base/time/default_clock.h" | 18 #include "base/time/default_clock.h" |
19 #include "base/time/time.h" | 19 #include "base/time/time.h" |
20 #include "base/values.h" | 20 #include "base/values.h" |
21 #include "chrome/browser/banners/app_banner_settings_helper.h" | 21 #include "chrome/browser/banners/app_banner_settings_helper.h" |
22 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 22 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 23 #include "chrome/browser/engagement/site_engagement_helper.h" |
23 #include "chrome/browser/engagement/site_engagement_metrics.h" | 24 #include "chrome/browser/engagement/site_engagement_metrics.h" |
24 #include "chrome/browser/engagement/site_engagement_score.h" | 25 #include "chrome/browser/engagement/site_engagement_score.h" |
25 #include "chrome/browser/engagement/site_engagement_service_factory.h" | 26 #include "chrome/browser/engagement/site_engagement_service_factory.h" |
26 #include "chrome/browser/history/history_service_factory.h" | 27 #include "chrome/browser/history/history_service_factory.h" |
27 #include "chrome/browser/profiles/profile.h" | 28 #include "chrome/browser/profiles/profile.h" |
28 #include "chrome/common/chrome_switches.h" | 29 #include "chrome/common/chrome_switches.h" |
29 #include "chrome/common/pref_names.h" | 30 #include "chrome/common/pref_names.h" |
30 #include "components/content_settings/core/browser/host_content_settings_map.h" | 31 #include "components/content_settings/core/browser/host_content_settings_map.h" |
31 #include "components/content_settings/core/common/content_settings_pattern.h" | 32 #include "components/content_settings/core/common/content_settings_pattern.h" |
32 #include "components/history/core/browser/history_service.h" | 33 #include "components/history/core/browser/history_service.h" |
33 #include "components/prefs/pref_service.h" | 34 #include "components/prefs/pref_service.h" |
34 #include "content/public/browser/browser_thread.h" | 35 #include "content/public/browser/browser_thread.h" |
| 36 #include "content/public/browser/render_frame_host.h" |
35 #include "content/public/browser/web_contents.h" | 37 #include "content/public/browser/web_contents.h" |
| 38 #include "content/public/common/associated_interface_provider.h" |
36 #include "url/gurl.h" | 39 #include "url/gurl.h" |
37 | 40 |
38 #if defined(OS_ANDROID) | 41 #if defined(OS_ANDROID) |
39 #include "chrome/browser/engagement/site_engagement_service_android.h" | 42 #include "chrome/browser/engagement/site_engagement_service_android.h" |
40 #endif | 43 #endif |
41 | 44 |
42 namespace { | 45 namespace { |
43 | 46 |
44 const int FOUR_WEEKS_IN_DAYS = 28; | 47 const int FOUR_WEEKS_IN_DAYS = 28; |
45 | 48 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 } | 122 } |
120 } | 123 } |
121 | 124 |
122 SiteEngagementService::~SiteEngagementService() { | 125 SiteEngagementService::~SiteEngagementService() { |
123 history::HistoryService* history = HistoryServiceFactory::GetForProfile( | 126 history::HistoryService* history = HistoryServiceFactory::GetForProfile( |
124 profile_, ServiceAccessType::IMPLICIT_ACCESS); | 127 profile_, ServiceAccessType::IMPLICIT_ACCESS); |
125 if (history) | 128 if (history) |
126 history->RemoveObserver(this); | 129 history->RemoveObserver(this); |
127 } | 130 } |
128 | 131 |
129 SiteEngagementService::EngagementLevel | 132 blink::mojom::EngagementLevel |
130 SiteEngagementService::GetEngagementLevel(const GURL& url) const { | 133 SiteEngagementService::GetEngagementLevel(const GURL& url) const { |
131 DCHECK_LT(SiteEngagementScore::GetMediumEngagementBoundary(), | 134 if (IsLastEngagementStale()) |
132 SiteEngagementScore::GetHighEngagementBoundary()); | 135 CleanupEngagementScores(true); |
133 double score = GetScore(url); | |
134 if (score == 0) | |
135 return ENGAGEMENT_LEVEL_NONE; | |
136 | 136 |
137 if (score < SiteEngagementScore::GetMediumEngagementBoundary()) | 137 return CreateEngagementScore(url).GetEngagementLevel(); |
138 return ENGAGEMENT_LEVEL_LOW; | |
139 | |
140 if (score < SiteEngagementScore::GetHighEngagementBoundary()) | |
141 return ENGAGEMENT_LEVEL_MEDIUM; | |
142 | |
143 if (score < SiteEngagementScore::kMaxPoints) | |
144 return ENGAGEMENT_LEVEL_HIGH; | |
145 | |
146 return ENGAGEMENT_LEVEL_MAX; | |
147 } | 138 } |
148 | 139 |
149 std::map<GURL, double> SiteEngagementService::GetScoreMap() const { | 140 std::map<GURL, double> SiteEngagementService::GetScoreMap() const { |
150 HostContentSettingsMap* settings_map = | 141 HostContentSettingsMap* settings_map = |
151 HostContentSettingsMapFactory::GetForProfile(profile_); | 142 HostContentSettingsMapFactory::GetForProfile(profile_); |
152 std::unique_ptr<ContentSettingsForOneType> engagement_settings = | 143 std::unique_ptr<ContentSettingsForOneType> engagement_settings = |
153 GetEngagementContentSettings(settings_map); | 144 GetEngagementContentSettings(settings_map); |
154 | 145 |
155 std::map<GURL, double> score_map; | 146 std::map<GURL, double> score_map; |
156 for (const auto& site : *engagement_settings) { | 147 for (const auto& site : *engagement_settings) { |
157 GURL origin(site.primary_pattern.ToString()); | 148 GURL origin(site.primary_pattern.ToString()); |
158 if (!origin.is_valid()) | 149 if (!origin.is_valid()) |
159 continue; | 150 continue; |
160 | 151 |
161 score_map[origin] = GetScore(origin); | 152 score_map[origin] = GetScore(origin); |
162 } | 153 } |
163 | 154 |
164 return score_map; | 155 return score_map; |
165 } | 156 } |
166 | 157 |
167 bool SiteEngagementService::IsBootstrapped() const { | 158 bool SiteEngagementService::IsBootstrapped() const { |
168 return GetTotalEngagementPoints() >= | 159 return GetTotalEngagementPoints() >= |
169 SiteEngagementScore::GetBootstrapPoints(); | 160 SiteEngagementScore::GetBootstrapPoints(); |
170 } | 161 } |
171 | 162 |
172 bool SiteEngagementService::IsEngagementAtLeast(const GURL& url, | 163 bool SiteEngagementService::IsEngagementAtLeast( |
173 EngagementLevel level) const { | 164 const GURL& url, |
| 165 blink::mojom::EngagementLevel level) const { |
174 DCHECK_LT(SiteEngagementScore::GetMediumEngagementBoundary(), | 166 DCHECK_LT(SiteEngagementScore::GetMediumEngagementBoundary(), |
175 SiteEngagementScore::GetHighEngagementBoundary()); | 167 SiteEngagementScore::GetHighEngagementBoundary()); |
176 double score = GetScore(url); | 168 double score = GetScore(url); |
177 switch (level) { | 169 switch (level) { |
178 case ENGAGEMENT_LEVEL_NONE: | 170 case blink::mojom::EngagementLevel::NONE: |
179 return true; | 171 return true; |
180 case ENGAGEMENT_LEVEL_LOW: | 172 case blink::mojom::EngagementLevel::MINIMAL: |
181 return score > 0; | 173 return score > 0; |
182 case ENGAGEMENT_LEVEL_MEDIUM: | 174 case blink::mojom::EngagementLevel::LOW: |
| 175 return score >= 1; |
| 176 case blink::mojom::EngagementLevel::MEDIUM: |
183 return score >= SiteEngagementScore::GetMediumEngagementBoundary(); | 177 return score >= SiteEngagementScore::GetMediumEngagementBoundary(); |
184 case ENGAGEMENT_LEVEL_HIGH: | 178 case blink::mojom::EngagementLevel::HIGH: |
185 return score >= SiteEngagementScore::GetHighEngagementBoundary(); | 179 return score >= SiteEngagementScore::GetHighEngagementBoundary(); |
186 case ENGAGEMENT_LEVEL_MAX: | 180 case blink::mojom::EngagementLevel::MAX: |
187 return score == SiteEngagementScore::kMaxPoints; | 181 return score == SiteEngagementScore::kMaxPoints; |
188 } | 182 } |
189 NOTREACHED(); | 183 NOTREACHED(); |
190 return false; | 184 return false; |
191 } | 185 } |
192 | 186 |
193 void SiteEngagementService::AddObserver(SiteEngagementObserver* observer) { | 187 void SiteEngagementService::AddObserver(SiteEngagementObserver* observer) { |
194 observer_list_.AddObserver(observer); | 188 observer_list_.AddObserver(observer); |
195 } | 189 } |
196 | 190 |
(...skipping 18 matching lines...) Expand all Loading... |
215 SiteEngagementMetrics::RecordDaysSinceLastShortcutLaunch( | 209 SiteEngagementMetrics::RecordDaysSinceLastShortcutLaunch( |
216 std::max(0, (now - last_launch).InDays())); | 210 std::max(0, (now - last_launch).InDays())); |
217 } | 211 } |
218 SiteEngagementMetrics::RecordEngagement( | 212 SiteEngagementMetrics::RecordEngagement( |
219 SiteEngagementMetrics::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH); | 213 SiteEngagementMetrics::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH); |
220 | 214 |
221 score.set_last_shortcut_launch_time(now); | 215 score.set_last_shortcut_launch_time(now); |
222 score.Commit(); | 216 score.Commit(); |
223 } | 217 } |
224 | 218 |
| 219 void SiteEngagementService::HelperCreated( |
| 220 SiteEngagementService::Helper* helper) { |
| 221 helpers_.insert(helper); |
| 222 } |
| 223 |
| 224 void SiteEngagementService::HelperDeleted( |
| 225 SiteEngagementService::Helper* helper) { |
| 226 helpers_.erase(helper); |
| 227 } |
| 228 |
225 double SiteEngagementService::GetScore(const GURL& url) const { | 229 double SiteEngagementService::GetScore(const GURL& url) const { |
226 // Ensure that if engagement is stale, we clean things up before fetching the | 230 // Ensure that if engagement is stale, we clean things up before fetching the |
227 // score. | 231 // score. |
228 if (IsLastEngagementStale()) | 232 if (IsLastEngagementStale()) |
229 CleanupEngagementScores(true); | 233 CleanupEngagementScores(true); |
230 | 234 |
231 return CreateEngagementScore(url).GetScore(); | 235 return CreateEngagementScore(url).GetScore(); |
232 } | 236 } |
233 | 237 |
234 double SiteEngagementService::GetTotalEngagementPoints() const { | 238 double SiteEngagementService::GetTotalEngagementPoints() const { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 if (points == 0) | 270 if (points == 0) |
267 return; | 271 return; |
268 | 272 |
269 // Trigger a cleanup and date adjustment if it has been a substantial length | 273 // Trigger a cleanup and date adjustment if it has been a substantial length |
270 // of time since *any* engagement was recorded by the service. This will | 274 // of time since *any* engagement was recorded by the service. This will |
271 // ensure that we do not decay scores when the user did not use the browser. | 275 // ensure that we do not decay scores when the user did not use the browser. |
272 if (IsLastEngagementStale()) | 276 if (IsLastEngagementStale()) |
273 CleanupEngagementScores(true); | 277 CleanupEngagementScores(true); |
274 | 278 |
275 SiteEngagementScore score = CreateEngagementScore(url); | 279 SiteEngagementScore score = CreateEngagementScore(url); |
| 280 blink::mojom::EngagementLevel old_level = score.GetEngagementLevel(); |
| 281 |
276 score.AddPoints(points); | 282 score.AddPoints(points); |
277 score.Commit(); | 283 score.Commit(); |
278 | 284 |
279 SetLastEngagementTime(score.last_engagement_time()); | 285 SetLastEngagementTime(score.last_engagement_time()); |
| 286 |
| 287 blink::mojom::EngagementLevel new_level = score.GetEngagementLevel(); |
| 288 if (old_level != new_level) |
| 289 SendLevelChangeToHelpers(url, new_level); |
280 } | 290 } |
281 | 291 |
282 void SiteEngagementService::AfterStartupTask() { | 292 void SiteEngagementService::AfterStartupTask() { |
283 // Check if we need to reset last engagement times on startup - we want to | 293 // Check if we need to reset last engagement times on startup - we want to |
284 // avoid doing this in AddPoints() if possible. It is still necessary to check | 294 // avoid doing this in AddPoints() if possible. It is still necessary to check |
285 // in AddPoints for people who never restart Chrome, but leave it open and | 295 // in AddPoints for people who never restart Chrome, but leave it open and |
286 // their computer on standby. | 296 // their computer on standby. |
287 CleanupEngagementScores(IsLastEngagementStale()); | 297 CleanupEngagementScores(IsLastEngagementStale()); |
288 RecordMetrics(); | 298 RecordMetrics(); |
289 } | 299 } |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 return; | 501 return; |
492 | 502 |
493 SiteEngagementMetrics::RecordEngagement(type); | 503 SiteEngagementMetrics::RecordEngagement(type); |
494 AddPoints(url, SiteEngagementScore::GetUserInputPoints()); | 504 AddPoints(url, SiteEngagementScore::GetUserInputPoints()); |
495 | 505 |
496 RecordMetrics(); | 506 RecordMetrics(); |
497 for (SiteEngagementObserver& observer : observer_list_) | 507 for (SiteEngagementObserver& observer : observer_list_) |
498 observer.OnEngagementIncreased(web_contents, url, GetScore(url)); | 508 observer.OnEngagementIncreased(web_contents, url, GetScore(url)); |
499 } | 509 } |
500 | 510 |
| 511 void SiteEngagementService::SendLevelChangeToHelpers( |
| 512 const GURL& url, |
| 513 blink::mojom::EngagementLevel level) { |
| 514 for (SiteEngagementService::Helper* helper : helpers_) |
| 515 helper->OnEngagementLevelChanged(url, level); |
| 516 } |
| 517 |
501 bool SiteEngagementService::IsLastEngagementStale() const { | 518 bool SiteEngagementService::IsLastEngagementStale() const { |
502 // Only happens on first run when no engagement has ever been recorded. | 519 // Only happens on first run when no engagement has ever been recorded. |
503 base::Time last_engagement_time = GetLastEngagementTime(); | 520 base::Time last_engagement_time = GetLastEngagementTime(); |
504 if (last_engagement_time.is_null()) | 521 if (last_engagement_time.is_null()) |
505 return false; | 522 return false; |
506 | 523 |
507 // Stale is either too *far* back, or any amount *forward* in time. This could | 524 // Stale is either too *far* back, or any amount *forward* in time. This could |
508 // occur due to a changed clock, or extended non-use of the browser. | 525 // occur due to a changed clock, or extended non-use of the browser. |
509 return (clock_->Now() - last_engagement_time) >= GetStalePeriod() || | 526 return (clock_->Now() - last_engagement_time) >= GetStalePeriod() || |
510 (clock_->Now() < last_engagement_time); | 527 (clock_->Now() < last_engagement_time); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 if (!engagement_score.last_shortcut_launch_time().is_null() && | 647 if (!engagement_score.last_shortcut_launch_time().is_null() && |
631 engagement_score.last_shortcut_launch_time() > last_visit) { | 648 engagement_score.last_shortcut_launch_time() > last_visit) { |
632 engagement_score.set_last_shortcut_launch_time(last_visit); | 649 engagement_score.set_last_shortcut_launch_time(last_visit); |
633 } | 650 } |
634 | 651 |
635 engagement_score.Commit(); | 652 engagement_score.Commit(); |
636 } | 653 } |
637 | 654 |
638 SetLastEngagementTime(now); | 655 SetLastEngagementTime(now); |
639 } | 656 } |
OLD | NEW |