| OLD | NEW | 
|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/banners/app_banner_settings_helper.h" | 5 #include "chrome/browser/banners/app_banner_settings_helper.h" | 
| 6 | 6 | 
| 7 #include <stddef.h> | 7 #include <stddef.h> | 
| 8 | 8 | 
| 9 #include <algorithm> | 9 #include <memory> | 
| 10 #include <string> | 10 #include <string> | 
| 11 #include <utility> | 11 #include <utility> | 
| 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" |  | 
| 16 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" | 
| 17 #include "base/strings/string_util.h" |  | 
| 18 #include "chrome/browser/banners/app_banner_manager.h" | 16 #include "chrome/browser/banners/app_banner_manager.h" | 
| 19 #include "chrome/browser/banners/app_banner_metrics.h" | 17 #include "chrome/browser/banners/app_banner_metrics.h" | 
| 20 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" | 
| 21 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 19 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 
| 22 #include "chrome/browser/installable/installable_logging.h" | 20 #include "chrome/browser/installable/installable_logging.h" | 
| 23 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" | 
| 24 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" | 
| 25 #include "components/content_settings/core/browser/host_content_settings_map.h" | 23 #include "components/content_settings/core/browser/host_content_settings_map.h" | 
| 26 #include "components/content_settings/core/common/content_settings_pattern.h" | 24 #include "components/content_settings/core/common/content_settings_pattern.h" | 
| 27 #include "components/rappor/rappor_utils.h" | 25 #include "components/rappor/rappor_utils.h" | 
| 28 #include "components/variations/variations_associated_data.h" | 26 #include "components/variations/variations_associated_data.h" | 
| 29 #include "content/public/browser/web_contents.h" | 27 #include "content/public/browser/web_contents.h" | 
| 30 #include "net/base/escape.h" |  | 
| 31 #include "url/gurl.h" | 28 #include "url/gurl.h" | 
| 32 | 29 | 
| 33 namespace { | 30 namespace { | 
| 34 | 31 | 
| 35 // Max number of apps (including ServiceWorker based web apps) that a particular | 32 // Max number of apps (including ServiceWorker based web apps) that a particular | 
| 36 // site may show a banner for. | 33 // site may show a banner for. | 
| 37 const size_t kMaxAppsPerSite = 3; | 34 const size_t kMaxAppsPerSite = 3; | 
| 38 | 35 | 
| 39 // Oldest could show banner event we care about, in days. |  | 
| 40 const unsigned int kOldestCouldShowBannerEventInDays = 14; |  | 
| 41 |  | 
| 42 // Default number of days that dismissing or ignoring the banner will prevent it | 36 // Default number of days that dismissing or ignoring the banner will prevent it | 
| 43 // being seen again for. | 37 // being seen again for. | 
| 44 const unsigned int kMinimumBannerBlockedToBannerShown = 90; | 38 const unsigned int kMinimumBannerBlockedToBannerShown = 90; | 
| 45 const unsigned int kMinimumDaysBetweenBannerShows = 14; | 39 const unsigned int kMinimumDaysBetweenBannerShows = 14; | 
| 46 | 40 | 
| 47 const unsigned int kNumberOfMinutesInADay = 1440; | 41 // Default site engagement required to trigger the banner. | 
| 48 |  | 
| 49 // Default scores assigned to direct and indirect navigations respectively. |  | 
| 50 const unsigned int kDefaultDirectNavigationEngagement = 1; |  | 
| 51 const unsigned int kDefaultIndirectNavigationEngagement = 1; |  | 
| 52 |  | 
| 53 // Default number of navigations required to trigger the banner. |  | 
| 54 const unsigned int kDefaultTotalEngagementToTrigger = 2; | 42 const unsigned int kDefaultTotalEngagementToTrigger = 2; | 
| 55 | 43 | 
| 56 // The number of days in the past that a site should be launched from homescreen | 44 // The number of days in the past that a site should be launched from homescreen | 
| 57 // to be considered recent. | 45 // to be considered recent. | 
| 58 // TODO(dominickn): work out how to unify this with | 46 // TODO(dominickn): work out how to unify this with | 
| 59 // WebappDataStorage.wasLaunchedRecently. | 47 // WebappDataStorage.wasLaunchedRecently. | 
| 60 const unsigned int kRecentLastLaunchInDays = 10; | 48 const unsigned int kRecentLastLaunchInDays = 10; | 
| 61 | 49 | 
| 62 // Dictionary keys to use for the events. | 50 // Dictionary keys to use for the events. Must be kept in sync with | 
|  | 51 // AppBannerEvent. | 
| 63 const char* kBannerEventKeys[] = { | 52 const char* kBannerEventKeys[] = { | 
| 64     "couldShowBannerEvents", | 53     "couldShowBannerEvents", | 
| 65     "didShowBannerEvent", | 54     "didShowBannerEvent", | 
| 66     "didBlockBannerEvent", | 55     "didBlockBannerEvent", | 
| 67     "didAddToHomescreenEvent", | 56     "didAddToHomescreenEvent", | 
| 68 }; | 57 }; | 
| 69 | 58 | 
| 70 // Keys to use when storing BannerEvent structs. |  | 
| 71 const char kBannerTimeKey[] = "time"; |  | 
| 72 const char kBannerEngagementKey[] = "engagement"; |  | 
| 73 |  | 
| 74 // Keys to use when querying the variations params. | 59 // Keys to use when querying the variations params. | 
| 75 const char kBannerParamsKey[] = "AppBannerTriggering"; | 60 const char kBannerParamsKey[] = "AppBannerTriggering"; | 
| 76 const char kBannerParamsDirectKey[] = "direct"; |  | 
| 77 const char kBannerParamsIndirectKey[] = "indirect"; |  | 
| 78 const char kBannerParamsTotalKey[] = "total"; |  | 
| 79 const char kBannerParamsMinutesKey[] = "minutes"; |  | 
| 80 const char kBannerParamsEngagementTotalKey[] = "site_engagement_total"; | 61 const char kBannerParamsEngagementTotalKey[] = "site_engagement_total"; | 
| 81 const char kBannerParamsDaysAfterBannerDismissedKey[] = "days_after_dismiss"; | 62 const char kBannerParamsDaysAfterBannerDismissedKey[] = "days_after_dismiss"; | 
| 82 const char kBannerParamsDaysAfterBannerIgnoredKey[] = "days_after_ignore"; | 63 const char kBannerParamsDaysAfterBannerIgnoredKey[] = "days_after_ignore"; | 
| 83 const char kBannerSiteEngagementParamsKey[] = "use_site_engagement"; |  | 
| 84 const char kBannerParamsLanguageKey[] = "language_option"; | 64 const char kBannerParamsLanguageKey[] = "language_option"; | 
| 85 | 65 | 
| 86 // Engagement weight assigned to direct and indirect navigations. |  | 
| 87 // By default, a direct navigation is a page visit via ui::PAGE_TRANSITION_TYPED |  | 
| 88 // or ui::PAGE_TRANSITION_GENERATED. |  | 
| 89 double gDirectNavigationEngagement = kDefaultDirectNavigationEngagement; |  | 
| 90 double gIndirectNavigationEnagagement = kDefaultIndirectNavigationEngagement; |  | 
| 91 |  | 
| 92 // Number of minutes between visits that will trigger a could show banner event. |  | 
| 93 // Defaults to the number of minutes in a day. |  | 
| 94 unsigned int gMinimumMinutesBetweenVisits = kNumberOfMinutesInADay; |  | 
| 95 |  | 
| 96 // Total engagement score required before a banner will actually be triggered. | 66 // Total engagement score required before a banner will actually be triggered. | 
| 97 double gTotalEngagementToTrigger = kDefaultTotalEngagementToTrigger; | 67 double gTotalEngagementToTrigger = kDefaultTotalEngagementToTrigger; | 
| 98 | 68 | 
| 99 unsigned int gDaysAfterDismissedToShow = kMinimumBannerBlockedToBannerShown; | 69 unsigned int gDaysAfterDismissedToShow = kMinimumBannerBlockedToBannerShown; | 
| 100 unsigned int gDaysAfterIgnoredToShow = kMinimumDaysBetweenBannerShows; | 70 unsigned int gDaysAfterIgnoredToShow = kMinimumDaysBetweenBannerShows; | 
| 101 | 71 | 
| 102 std::unique_ptr<base::DictionaryValue> GetOriginDict( | 72 std::unique_ptr<base::DictionaryValue> GetOriginDict( | 
| 103     HostContentSettingsMap* settings, | 73     HostContentSettingsMap* settings, | 
| 104     const GURL& origin_url) { | 74     const GURL& origin_url) { | 
| 105   if (!settings) | 75   if (!settings) | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 123     if (origin_dict->size() < kMaxAppsPerSite) { | 93     if (origin_dict->size() < kMaxAppsPerSite) { | 
| 124       app_dict = new base::DictionaryValue(); | 94       app_dict = new base::DictionaryValue(); | 
| 125       origin_dict->SetWithoutPathExpansion(key_name, | 95       origin_dict->SetWithoutPathExpansion(key_name, | 
| 126                                            base::WrapUnique(app_dict)); | 96                                            base::WrapUnique(app_dict)); | 
| 127     } | 97     } | 
| 128   } | 98   } | 
| 129 | 99 | 
| 130   return app_dict; | 100   return app_dict; | 
| 131 } | 101 } | 
| 132 | 102 | 
| 133 double GetEventEngagement(ui::PageTransition transition_type) { |  | 
| 134   if (ui::PageTransitionCoreTypeIs(transition_type, |  | 
| 135                                    ui::PAGE_TRANSITION_TYPED) || |  | 
| 136       ui::PageTransitionCoreTypeIs(transition_type, |  | 
| 137                                    ui::PAGE_TRANSITION_GENERATED)) { |  | 
| 138     return gDirectNavigationEngagement; |  | 
| 139   } else { |  | 
| 140     return gIndirectNavigationEnagagement; |  | 
| 141   } |  | 
| 142 } |  | 
| 143 |  | 
| 144 // Queries variations for the number of days which dismissing and ignoring the | 103 // Queries variations for the number of days which dismissing and ignoring the | 
| 145 // banner should prevent a banner from showing. | 104 // banner should prevent a banner from showing. | 
| 146 void UpdateDaysBetweenShowing() { | 105 void UpdateDaysBetweenShowing() { | 
| 147   std::string dismiss_param = variations::GetVariationParamValue( | 106   std::string dismiss_param = variations::GetVariationParamValue( | 
| 148       kBannerParamsKey, kBannerParamsDaysAfterBannerDismissedKey); | 107       kBannerParamsKey, kBannerParamsDaysAfterBannerDismissedKey); | 
| 149   std::string ignore_param = variations::GetVariationParamValue( | 108   std::string ignore_param = variations::GetVariationParamValue( | 
| 150       kBannerParamsKey, kBannerParamsDaysAfterBannerIgnoredKey); | 109       kBannerParamsKey, kBannerParamsDaysAfterBannerIgnoredKey); | 
| 151 | 110 | 
| 152   if (!dismiss_param.empty() && !ignore_param.empty()) { | 111   if (!dismiss_param.empty() && !ignore_param.empty()) { | 
| 153     unsigned int dismiss_days = 0; | 112     unsigned int dismiss_days = 0; | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 170   if (!total_param.empty()) { | 129   if (!total_param.empty()) { | 
| 171     double total_engagement = -1; | 130     double total_engagement = -1; | 
| 172 | 131 | 
| 173     if (base::StringToDouble(total_param, &total_engagement) && | 132     if (base::StringToDouble(total_param, &total_engagement) && | 
| 174         total_engagement >= 0) { | 133         total_engagement >= 0) { | 
| 175       AppBannerSettingsHelper::SetTotalEngagementToTrigger(total_engagement); | 134       AppBannerSettingsHelper::SetTotalEngagementToTrigger(total_engagement); | 
| 176     } | 135     } | 
| 177   } | 136   } | 
| 178 } | 137 } | 
| 179 | 138 | 
| 180 // Queries variations for updates to the default engagement values assigned |  | 
| 181 // to direct and indirect navigations. |  | 
| 182 void UpdateEngagementWeights() { |  | 
| 183   std::string direct_param = variations::GetVariationParamValue( |  | 
| 184       kBannerParamsKey, kBannerParamsDirectKey); |  | 
| 185   std::string indirect_param = variations::GetVariationParamValue( |  | 
| 186       kBannerParamsKey, kBannerParamsIndirectKey); |  | 
| 187   std::string total_param = variations::GetVariationParamValue( |  | 
| 188       kBannerParamsKey, kBannerParamsTotalKey); |  | 
| 189 |  | 
| 190   if (!direct_param.empty() && !indirect_param.empty() && |  | 
| 191       !total_param.empty()) { |  | 
| 192     double direct_engagement = -1; |  | 
| 193     double indirect_engagement = -1; |  | 
| 194     double total_engagement = -1; |  | 
| 195 |  | 
| 196     // Ensure that we get valid doubles from the field trial, and that both |  | 
| 197     // values are greater than or equal to zero and less than or equal to the |  | 
| 198     // total engagement required to trigger the banner. |  | 
| 199     if (base::StringToDouble(direct_param, &direct_engagement) && |  | 
| 200         base::StringToDouble(indirect_param, &indirect_engagement) && |  | 
| 201         base::StringToDouble(total_param, &total_engagement) && |  | 
| 202         direct_engagement >= 0 && indirect_engagement >= 0 && |  | 
| 203         total_engagement > 0 && direct_engagement <= total_engagement && |  | 
| 204         indirect_engagement <= total_engagement) { |  | 
| 205       AppBannerSettingsHelper::SetEngagementWeights(direct_engagement, |  | 
| 206                                                     indirect_engagement); |  | 
| 207       AppBannerSettingsHelper::SetTotalEngagementToTrigger(total_engagement); |  | 
| 208     } |  | 
| 209   } |  | 
| 210 } |  | 
| 211 |  | 
| 212 // Queries variation for updates to the default number of minutes between |  | 
| 213 // site visits counted for the purposes of displaying a banner. |  | 
| 214 void UpdateMinutesBetweenVisits() { |  | 
| 215   std::string param = variations::GetVariationParamValue( |  | 
| 216       kBannerParamsKey, kBannerParamsMinutesKey); |  | 
| 217   if (!param.empty()) { |  | 
| 218     int minimum_minutes = 0; |  | 
| 219     if (base::StringToInt(param, &minimum_minutes)) |  | 
| 220       AppBannerSettingsHelper::SetMinimumMinutesBetweenVisits(minimum_minutes); |  | 
| 221   } |  | 
| 222 } |  | 
| 223 |  | 
| 224 }  // namespace | 139 }  // namespace | 
| 225 | 140 | 
| 226 // Key to store instant apps events. | 141 // Key to store instant apps events. | 
| 227 const char AppBannerSettingsHelper::kInstantAppsKey[] = "instantapps"; | 142 const char AppBannerSettingsHelper::kInstantAppsKey[] = "instantapps"; | 
| 228 | 143 | 
| 229 void AppBannerSettingsHelper::ClearHistoryForURLs( | 144 void AppBannerSettingsHelper::ClearHistoryForURLs( | 
| 230     Profile* profile, | 145     Profile* profile, | 
| 231     const std::set<GURL>& origin_urls) { | 146     const std::set<GURL>& origin_urls) { | 
| 232   HostContentSettingsMap* settings = | 147   HostContentSettingsMap* settings = | 
| 233       HostContentSettingsMapFactory::GetForProfile(profile); | 148       HostContentSettingsMapFactory::GetForProfile(profile); | 
| 234   for (const GURL& origin_url : origin_urls) { | 149   for (const GURL& origin_url : origin_urls) { | 
| 235     settings->SetWebsiteSettingDefaultScope(origin_url, GURL(), | 150     settings->SetWebsiteSettingDefaultScope(origin_url, GURL(), | 
| 236                                             CONTENT_SETTINGS_TYPE_APP_BANNER, | 151                                             CONTENT_SETTINGS_TYPE_APP_BANNER, | 
| 237                                             std::string(), nullptr); | 152                                             std::string(), nullptr); | 
| 238     settings->FlushLossyWebsiteSettings(); | 153     settings->FlushLossyWebsiteSettings(); | 
| 239   } | 154   } | 
| 240 } | 155 } | 
| 241 | 156 | 
| 242 void AppBannerSettingsHelper::RecordBannerInstallEvent( | 157 void AppBannerSettingsHelper::RecordBannerInstallEvent( | 
| 243     content::WebContents* web_contents, | 158     content::WebContents* web_contents, | 
| 244     const std::string& package_name_or_start_url, | 159     const std::string& package_name_or_start_url, | 
| 245     AppBannerRapporMetric rappor_metric) { | 160     AppBannerRapporMetric rappor_metric) { | 
| 246   banners::TrackInstallEvent(banners::INSTALL_EVENT_WEB_APP_INSTALLED); | 161   banners::TrackInstallEvent(banners::INSTALL_EVENT_WEB_APP_INSTALLED); | 
| 247 | 162 | 
| 248   AppBannerSettingsHelper::RecordBannerEvent( | 163   AppBannerSettingsHelper::RecordBannerEvent( | 
| 249       web_contents, web_contents->GetURL(), package_name_or_start_url, | 164       web_contents, web_contents->GetLastCommittedURL(), | 
|  | 165       package_name_or_start_url, | 
| 250       AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN, | 166       AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN, | 
| 251       banners::AppBannerManager::GetCurrentTime()); | 167       banners::AppBannerManager::GetCurrentTime()); | 
| 252 | 168 | 
| 253   rappor::SampleDomainAndRegistryFromGURL( | 169   rappor::SampleDomainAndRegistryFromGURL( | 
| 254       g_browser_process->rappor_service(), | 170       g_browser_process->rappor_service(), | 
| 255       (rappor_metric == WEB ? "AppBanner.WebApp.Installed" | 171       (rappor_metric == WEB ? "AppBanner.WebApp.Installed" | 
| 256                             : "AppBanner.NativeApp.Installed"), | 172                             : "AppBanner.NativeApp.Installed"), | 
| 257       web_contents->GetURL()); | 173       web_contents->GetLastCommittedURL()); | 
| 258 } | 174 } | 
| 259 | 175 | 
| 260 void AppBannerSettingsHelper::RecordBannerDismissEvent( | 176 void AppBannerSettingsHelper::RecordBannerDismissEvent( | 
| 261     content::WebContents* web_contents, | 177     content::WebContents* web_contents, | 
| 262     const std::string& package_name_or_start_url, | 178     const std::string& package_name_or_start_url, | 
| 263     AppBannerRapporMetric rappor_metric) { | 179     AppBannerRapporMetric rappor_metric) { | 
| 264   banners::TrackDismissEvent(banners::DISMISS_EVENT_CLOSE_BUTTON); | 180   banners::TrackDismissEvent(banners::DISMISS_EVENT_CLOSE_BUTTON); | 
| 265 | 181 | 
| 266   AppBannerSettingsHelper::RecordBannerEvent( | 182   AppBannerSettingsHelper::RecordBannerEvent( | 
| 267       web_contents, web_contents->GetURL(), package_name_or_start_url, | 183       web_contents, web_contents->GetLastCommittedURL(), | 
|  | 184       package_name_or_start_url, | 
| 268       AppBannerSettingsHelper::APP_BANNER_EVENT_DID_BLOCK, | 185       AppBannerSettingsHelper::APP_BANNER_EVENT_DID_BLOCK, | 
| 269       banners::AppBannerManager::GetCurrentTime()); | 186       banners::AppBannerManager::GetCurrentTime()); | 
| 270 | 187 | 
| 271   rappor::SampleDomainAndRegistryFromGURL( | 188   rappor::SampleDomainAndRegistryFromGURL( | 
| 272       g_browser_process->rappor_service(), | 189       g_browser_process->rappor_service(), | 
| 273       (rappor_metric == WEB ? "AppBanner.WebApp.Dismissed" | 190       (rappor_metric == WEB ? "AppBanner.WebApp.Dismissed" | 
| 274                             : "AppBanner.NativeApp.Dismissed"), | 191                             : "AppBanner.NativeApp.Dismissed"), | 
| 275       web_contents->GetURL()); | 192       web_contents->GetLastCommittedURL()); | 
| 276 } | 193 } | 
| 277 | 194 | 
| 278 void AppBannerSettingsHelper::RecordBannerEvent( | 195 void AppBannerSettingsHelper::RecordBannerEvent( | 
| 279     content::WebContents* web_contents, | 196     content::WebContents* web_contents, | 
| 280     const GURL& origin_url, | 197     const GURL& origin_url, | 
| 281     const std::string& package_name_or_start_url, | 198     const std::string& package_name_or_start_url, | 
| 282     AppBannerEvent event, | 199     AppBannerEvent event, | 
| 283     base::Time time) { | 200     base::Time time) { | 
| 284   DCHECK(event != APP_BANNER_EVENT_COULD_SHOW); |  | 
| 285 |  | 
| 286   Profile* profile = | 201   Profile* profile = | 
| 287       Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 202       Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 
| 288   if (profile->IsOffTheRecord() || package_name_or_start_url.empty()) | 203   if (profile->IsOffTheRecord() || package_name_or_start_url.empty()) | 
| 289     return; | 204     return; | 
| 290 | 205 | 
| 291   HostContentSettingsMap* settings = | 206   HostContentSettingsMap* settings = | 
| 292       HostContentSettingsMapFactory::GetForProfile(profile); | 207       HostContentSettingsMapFactory::GetForProfile(profile); | 
| 293   std::unique_ptr<base::DictionaryValue> origin_dict = | 208   std::unique_ptr<base::DictionaryValue> origin_dict = | 
| 294       GetOriginDict(settings, origin_url); | 209       GetOriginDict(settings, origin_url); | 
| 295   if (!origin_dict) | 210   if (!origin_dict) | 
| 296     return; | 211     return; | 
| 297 | 212 | 
| 298   base::DictionaryValue* app_dict = | 213   base::DictionaryValue* app_dict = | 
| 299       GetAppDict(origin_dict.get(), package_name_or_start_url); | 214       GetAppDict(origin_dict.get(), package_name_or_start_url); | 
| 300   if (!app_dict) | 215   if (!app_dict) | 
| 301     return; | 216     return; | 
| 302 | 217 | 
| 303   // Dates are stored in their raw form (i.e. not local dates) to be resilient | 218   // Dates are stored in their raw form (i.e. not local dates) to be resilient | 
| 304   // to time zone changes. | 219   // to time zone changes. | 
| 305   std::string event_key(kBannerEventKeys[event]); | 220   std::string event_key(kBannerEventKeys[event]); | 
|  | 221 | 
|  | 222   if (event == APP_BANNER_EVENT_COULD_SHOW) { | 
|  | 223     // Do not overwrite a could show event, as this is used for metrics. | 
|  | 224     double internal_date; | 
|  | 225     if (app_dict->GetDouble(event_key, &internal_date)) | 
|  | 226       return; | 
|  | 227   } | 
| 306   app_dict->SetDouble(event_key, time.ToInternalValue()); | 228   app_dict->SetDouble(event_key, time.ToInternalValue()); | 
| 307 | 229 | 
| 308   settings->SetWebsiteSettingDefaultScope( | 230   settings->SetWebsiteSettingDefaultScope( | 
| 309       origin_url, GURL(), CONTENT_SETTINGS_TYPE_APP_BANNER, std::string(), | 231       origin_url, GURL(), CONTENT_SETTINGS_TYPE_APP_BANNER, std::string(), | 
| 310       std::move(origin_dict)); | 232       std::move(origin_dict)); | 
| 311 | 233 | 
| 312   // App banner content settings are lossy, meaning they will not cause the | 234   // App banner content settings are lossy, meaning they will not cause the | 
| 313   // prefs to become dirty. This is fine for most events, as if they are lost it | 235   // prefs to become dirty. This is fine for most events, as if they are lost it | 
| 314   // just means the user will have to engage a little bit more. However the | 236   // just means the user will have to engage a little bit more. However the | 
| 315   // DID_ADD_TO_HOMESCREEN event should always be recorded to prevent | 237   // DID_ADD_TO_HOMESCREEN event should always be recorded to prevent | 
| 316   // spamminess. | 238   // spamminess. | 
| 317   if (event == APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN) | 239   if (event == APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN) | 
| 318     settings->FlushLossyWebsiteSettings(); | 240     settings->FlushLossyWebsiteSettings(); | 
| 319 } | 241 } | 
| 320 | 242 | 
| 321 void AppBannerSettingsHelper::RecordBannerCouldShowEvent( |  | 
| 322     content::WebContents* web_contents, |  | 
| 323     const GURL& origin_url, |  | 
| 324     const std::string& package_name_or_start_url, |  | 
| 325     base::Time time, |  | 
| 326     ui::PageTransition transition_type) { |  | 
| 327   Profile* profile = |  | 
| 328       Profile::FromBrowserContext(web_contents->GetBrowserContext()); |  | 
| 329   if (profile->IsOffTheRecord() || package_name_or_start_url.empty()) |  | 
| 330     return; |  | 
| 331 |  | 
| 332   HostContentSettingsMap* settings = |  | 
| 333       HostContentSettingsMapFactory::GetForProfile(profile); |  | 
| 334   std::unique_ptr<base::DictionaryValue> origin_dict = |  | 
| 335       GetOriginDict(settings, origin_url); |  | 
| 336   if (!origin_dict) |  | 
| 337     return; |  | 
| 338 |  | 
| 339   base::DictionaryValue* app_dict = |  | 
| 340       GetAppDict(origin_dict.get(), package_name_or_start_url); |  | 
| 341   if (!app_dict) |  | 
| 342     return; |  | 
| 343 |  | 
| 344   std::string event_key(kBannerEventKeys[APP_BANNER_EVENT_COULD_SHOW]); |  | 
| 345   double engagement = GetEventEngagement(transition_type); |  | 
| 346 |  | 
| 347   base::ListValue* could_show_list = nullptr; |  | 
| 348   if (!app_dict->GetList(event_key, &could_show_list)) { |  | 
| 349     could_show_list = new base::ListValue(); |  | 
| 350     app_dict->Set(event_key, base::WrapUnique(could_show_list)); |  | 
| 351   } |  | 
| 352 |  | 
| 353   // Trim any items that are older than we should care about. For comparisons |  | 
| 354   // the times are converted to local dates. |  | 
| 355   base::Time date = BucketTimeToResolution(time, gMinimumMinutesBetweenVisits); |  | 
| 356   for (auto it = could_show_list->begin(); it != could_show_list->end();) { |  | 
| 357     if ((*it)->IsType(base::Value::TYPE_DICTIONARY)) { |  | 
| 358       base::DictionaryValue* internal_value; |  | 
| 359       double internal_date; |  | 
| 360       (*it)->GetAsDictionary(&internal_value); |  | 
| 361 |  | 
| 362       if (internal_value->GetDouble(kBannerTimeKey, &internal_date)) { |  | 
| 363         base::Time other_date = |  | 
| 364             BucketTimeToResolution(base::Time::FromInternalValue(internal_date), |  | 
| 365                                    gMinimumMinutesBetweenVisits); |  | 
| 366         if (other_date == date) { |  | 
| 367           double other_engagement = 0; |  | 
| 368           if (internal_value->GetDouble(kBannerEngagementKey, |  | 
| 369                                         &other_engagement) && |  | 
| 370               other_engagement >= engagement) { |  | 
| 371             // This date has already been added, but with an equal or higher |  | 
| 372             // engagement. Don't add the date again. If the conditional fails, |  | 
| 373             // fall to the end of the loop where the existing entry is deleted. |  | 
| 374             return; |  | 
| 375           } |  | 
| 376         } else { |  | 
| 377           base::TimeDelta delta = date - other_date; |  | 
| 378           if (delta < |  | 
| 379               base::TimeDelta::FromDays(kOldestCouldShowBannerEventInDays)) { |  | 
| 380             ++it; |  | 
| 381             continue; |  | 
| 382           } |  | 
| 383         } |  | 
| 384       } |  | 
| 385     } |  | 
| 386 |  | 
| 387     // Either this date is older than we care about, or it isn't in the correct |  | 
| 388     // format, or it is the same as the current date but with a lower |  | 
| 389     // engagement, so remove it. |  | 
| 390     it = could_show_list->Erase(it, nullptr); |  | 
| 391   } |  | 
| 392 |  | 
| 393   // Dates are stored in their raw form (i.e. not local dates) to be resilient |  | 
| 394   // to time zone changes. |  | 
| 395   std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |  | 
| 396   value->SetDouble(kBannerTimeKey, time.ToInternalValue()); |  | 
| 397   value->SetDouble(kBannerEngagementKey, engagement); |  | 
| 398   could_show_list->Append(std::move(value)); |  | 
| 399 |  | 
| 400   settings->SetWebsiteSettingDefaultScope( |  | 
| 401       origin_url, GURL(), CONTENT_SETTINGS_TYPE_APP_BANNER, std::string(), |  | 
| 402       std::move(origin_dict)); |  | 
| 403 } |  | 
| 404 |  | 
| 405 InstallableStatusCode AppBannerSettingsHelper::ShouldShowBanner( | 243 InstallableStatusCode AppBannerSettingsHelper::ShouldShowBanner( | 
| 406     content::WebContents* web_contents, | 244     content::WebContents* web_contents, | 
| 407     const GURL& origin_url, | 245     const GURL& origin_url, | 
| 408     const std::string& package_name_or_start_url, | 246     const std::string& package_name_or_start_url, | 
| 409     base::Time time) { | 247     base::Time time) { | 
| 410   // Ignore all checks if the flag to do so is set. | 248   // Ignore all checks if the flag to do so is set. | 
| 411   if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 249   if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 
| 412           switches::kBypassAppBannerEngagementChecks)) { | 250           switches::kBypassAppBannerEngagementChecks)) { | 
| 413     return NO_ERROR_DETECTED; | 251     return NO_ERROR_DETECTED; | 
| 414   } | 252   } | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 435     return PREVIOUSLY_BLOCKED; | 273     return PREVIOUSLY_BLOCKED; | 
| 436   } | 274   } | 
| 437 | 275 | 
| 438   base::Time shown_time = | 276   base::Time shown_time = | 
| 439       GetSingleBannerEvent(web_contents, origin_url, package_name_or_start_url, | 277       GetSingleBannerEvent(web_contents, origin_url, package_name_or_start_url, | 
| 440                            APP_BANNER_EVENT_DID_SHOW); | 278                            APP_BANNER_EVENT_DID_SHOW); | 
| 441   if (time - shown_time < base::TimeDelta::FromDays(gDaysAfterIgnoredToShow)) { | 279   if (time - shown_time < base::TimeDelta::FromDays(gDaysAfterIgnoredToShow)) { | 
| 442     return PREVIOUSLY_IGNORED; | 280     return PREVIOUSLY_IGNORED; | 
| 443   } | 281   } | 
| 444 | 282 | 
| 445   // If we have gotten this far and want to use site engagement, the banner flow |  | 
| 446   // was triggered by the site engagement service informing the banner manager |  | 
| 447   // that sufficient engagement has been accumulated. Hence there is no need to |  | 
| 448   // check the total amount of engagement. |  | 
| 449   // TODO(dominickn): just return true here and remove all of the following code |  | 
| 450   // in this method when app banners have fully migrated to using site |  | 
| 451   // engagement as a trigger condition. See crbug.com/616322. |  | 
| 452   // Do not do engagement checks for instant app banners. |  | 
| 453   if (ShouldUseSiteEngagementScore() || |  | 
| 454       package_name_or_start_url == kInstantAppsKey) { |  | 
| 455     return NO_ERROR_DETECTED; |  | 
| 456   } |  | 
| 457 |  | 
| 458   double total_engagement = 0; |  | 
| 459   std::vector<BannerEvent> could_show_events = GetCouldShowBannerEvents( |  | 
| 460       web_contents, origin_url, package_name_or_start_url); |  | 
| 461 |  | 
| 462   for (const auto& event : could_show_events) |  | 
| 463     total_engagement += event.engagement; |  | 
| 464 |  | 
| 465   if (!HasSufficientEngagement(total_engagement)) |  | 
| 466     return INSUFFICIENT_ENGAGEMENT; |  | 
| 467 |  | 
| 468   return NO_ERROR_DETECTED; | 283   return NO_ERROR_DETECTED; | 
| 469 } | 284 } | 
| 470 | 285 | 
| 471 std::vector<AppBannerSettingsHelper::BannerEvent> |  | 
| 472 AppBannerSettingsHelper::GetCouldShowBannerEvents( |  | 
| 473     content::WebContents* web_contents, |  | 
| 474     const GURL& origin_url, |  | 
| 475     const std::string& package_name_or_start_url) { |  | 
| 476   std::vector<BannerEvent> result; |  | 
| 477 |  | 
| 478   Profile* profile = |  | 
| 479       Profile::FromBrowserContext(web_contents->GetBrowserContext()); |  | 
| 480   HostContentSettingsMap* settings = |  | 
| 481       HostContentSettingsMapFactory::GetForProfile(profile); |  | 
| 482   std::unique_ptr<base::DictionaryValue> origin_dict = |  | 
| 483       GetOriginDict(settings, origin_url); |  | 
| 484 |  | 
| 485   if (!origin_dict) |  | 
| 486     return result; |  | 
| 487 |  | 
| 488   base::DictionaryValue* app_dict = |  | 
| 489       GetAppDict(origin_dict.get(), package_name_or_start_url); |  | 
| 490   if (!app_dict) |  | 
| 491     return result; |  | 
| 492 |  | 
| 493   std::string event_key(kBannerEventKeys[APP_BANNER_EVENT_COULD_SHOW]); |  | 
| 494   base::ListValue* could_show_list = nullptr; |  | 
| 495   if (!app_dict->GetList(event_key, &could_show_list)) |  | 
| 496     return result; |  | 
| 497 |  | 
| 498   for (const auto& value : *could_show_list) { |  | 
| 499     if (value->IsType(base::Value::TYPE_DICTIONARY)) { |  | 
| 500       base::DictionaryValue* internal_value; |  | 
| 501       double internal_date = 0; |  | 
| 502       value->GetAsDictionary(&internal_value); |  | 
| 503       double engagement = 0; |  | 
| 504 |  | 
| 505       if (internal_value->GetDouble(kBannerTimeKey, &internal_date) && |  | 
| 506           internal_value->GetDouble(kBannerEngagementKey, &engagement)) { |  | 
| 507         base::Time date = base::Time::FromInternalValue(internal_date); |  | 
| 508         result.push_back({date, engagement}); |  | 
| 509       } |  | 
| 510     } |  | 
| 511   } |  | 
| 512 |  | 
| 513   return result; |  | 
| 514 } |  | 
| 515 |  | 
| 516 base::Time AppBannerSettingsHelper::GetSingleBannerEvent( | 286 base::Time AppBannerSettingsHelper::GetSingleBannerEvent( | 
| 517     content::WebContents* web_contents, | 287     content::WebContents* web_contents, | 
| 518     const GURL& origin_url, | 288     const GURL& origin_url, | 
| 519     const std::string& package_name_or_start_url, | 289     const std::string& package_name_or_start_url, | 
| 520     AppBannerEvent event) { | 290     AppBannerEvent event) { | 
| 521   DCHECK(event != APP_BANNER_EVENT_COULD_SHOW); |  | 
| 522   DCHECK(event < APP_BANNER_EVENT_NUM_EVENTS); | 291   DCHECK(event < APP_BANNER_EVENT_NUM_EVENTS); | 
| 523 | 292 | 
| 524   Profile* profile = | 293   Profile* profile = | 
| 525       Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 294       Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 
| 526   HostContentSettingsMap* settings = | 295   HostContentSettingsMap* settings = | 
| 527       HostContentSettingsMapFactory::GetForProfile(profile); | 296       HostContentSettingsMapFactory::GetForProfile(profile); | 
| 528   std::unique_ptr<base::DictionaryValue> origin_dict = | 297   std::unique_ptr<base::DictionaryValue> origin_dict = | 
| 529       GetOriginDict(settings, origin_url); | 298       GetOriginDict(settings, origin_url); | 
| 530 | 299 | 
| 531   if (!origin_dict) | 300   if (!origin_dict) | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 548   return (base::CommandLine::ForCurrentProcess()->HasSwitch( | 317   return (base::CommandLine::ForCurrentProcess()->HasSwitch( | 
| 549              switches::kBypassAppBannerEngagementChecks)) || | 318              switches::kBypassAppBannerEngagementChecks)) || | 
| 550          (total_engagement >= gTotalEngagementToTrigger); | 319          (total_engagement >= gTotalEngagementToTrigger); | 
| 551 } | 320 } | 
| 552 | 321 | 
| 553 void AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow( | 322 void AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow( | 
| 554     content::WebContents* web_contents, | 323     content::WebContents* web_contents, | 
| 555     const GURL& origin_url, | 324     const GURL& origin_url, | 
| 556     const std::string& package_name_or_start_url, | 325     const std::string& package_name_or_start_url, | 
| 557     base::Time time) { | 326     base::Time time) { | 
| 558   std::vector<BannerEvent> could_show_events = GetCouldShowBannerEvents( | 327   base::Time could_show_time = | 
| 559       web_contents, origin_url, package_name_or_start_url); | 328       GetSingleBannerEvent(web_contents, origin_url, package_name_or_start_url, | 
|  | 329                            APP_BANNER_EVENT_COULD_SHOW); | 
| 560 | 330 | 
| 561   int minutes = 0; | 331   int minutes = 0; | 
| 562   if (could_show_events.size()) | 332   if (!could_show_time.is_null()) | 
| 563     minutes = (time - could_show_events[0].time).InMinutes(); | 333     minutes = (time - could_show_time).InMinutes(); | 
| 564 | 334 | 
| 565   banners::TrackMinutesFromFirstVisitToBannerShown(minutes); | 335   banners::TrackMinutesFromFirstVisitToBannerShown(minutes); | 
| 566 } | 336 } | 
| 567 | 337 | 
| 568 bool AppBannerSettingsHelper::WasLaunchedRecently(Profile* profile, | 338 bool AppBannerSettingsHelper::WasLaunchedRecently(Profile* profile, | 
| 569                                                   const GURL& origin_url, | 339                                                   const GURL& origin_url, | 
| 570                                                   base::Time now) { | 340                                                   base::Time now) { | 
| 571   HostContentSettingsMap* settings = | 341   HostContentSettingsMap* settings = | 
| 572       HostContentSettingsMapFactory::GetForProfile(profile); | 342       HostContentSettingsMapFactory::GetForProfile(profile); | 
| 573   std::unique_ptr<base::DictionaryValue> origin_dict = | 343   std::unique_ptr<base::DictionaryValue> origin_dict = | 
| 574       GetOriginDict(settings, origin_url); | 344       GetOriginDict(settings, origin_url); | 
| 575 | 345 | 
| 576   if (!origin_dict) | 346   if (!origin_dict) | 
| 577     return false; | 347     return false; | 
| 578 | 348 | 
| 579   // Iterate over everything in the content setting, which should be a set of | 349   // Iterate over everything in the content setting, which should be a set of | 
| 580   // dictionaries per app path. If we find one that has been added to | 350   // dictionaries per app path. If we find one that has been added to | 
| 581   // homescreen recently, return true. | 351   // homescreen recently, return true. | 
|  | 352   base::TimeDelta recent_last_launch_in_days = | 
|  | 353       base::TimeDelta::FromDays(kRecentLastLaunchInDays); | 
| 582   for (base::DictionaryValue::Iterator it(*origin_dict); !it.IsAtEnd(); | 354   for (base::DictionaryValue::Iterator it(*origin_dict); !it.IsAtEnd(); | 
| 583        it.Advance()) { | 355        it.Advance()) { | 
| 584     if (it.value().IsType(base::Value::TYPE_DICTIONARY)) { | 356     if (it.value().IsType(base::Value::TYPE_DICTIONARY)) { | 
| 585       const base::DictionaryValue* value; | 357       const base::DictionaryValue* value; | 
| 586       it.value().GetAsDictionary(&value); | 358       it.value().GetAsDictionary(&value); | 
| 587 | 359 | 
| 588       std::string event_key( | 360       std::string event_key( | 
| 589           kBannerEventKeys[APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN]); | 361           kBannerEventKeys[APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN]); | 
| 590       double internal_time; | 362       double internal_time; | 
| 591       if (it.key() == kInstantAppsKey || | 363       if (it.key() == kInstantAppsKey || | 
| 592           !value->GetDouble(event_key, &internal_time)) { | 364           !value->GetDouble(event_key, &internal_time)) { | 
| 593         continue; | 365         continue; | 
| 594       } | 366       } | 
| 595 | 367 | 
| 596       base::Time added_time = base::Time::FromInternalValue(internal_time); | 368       if ((now - base::Time::FromInternalValue(internal_time)) <= | 
| 597 | 369           recent_last_launch_in_days) { | 
| 598       if ((now - added_time) <= |  | 
| 599           base::TimeDelta::FromDays(kRecentLastLaunchInDays)) { |  | 
| 600         return true; | 370         return true; | 
| 601       } | 371       } | 
| 602     } | 372     } | 
| 603   } | 373   } | 
| 604 | 374 | 
| 605   return false; | 375   return false; | 
| 606 } | 376 } | 
| 607 | 377 | 
| 608 void AppBannerSettingsHelper::SetDaysAfterDismissAndIgnoreToTrigger( | 378 void AppBannerSettingsHelper::SetDaysAfterDismissAndIgnoreToTrigger( | 
| 609     unsigned int dismiss_days, | 379     unsigned int dismiss_days, | 
| 610     unsigned int ignore_days) { | 380     unsigned int ignore_days) { | 
| 611   gDaysAfterDismissedToShow = dismiss_days; | 381   gDaysAfterDismissedToShow = dismiss_days; | 
| 612   gDaysAfterIgnoredToShow = ignore_days; | 382   gDaysAfterIgnoredToShow = ignore_days; | 
| 613 } | 383 } | 
| 614 | 384 | 
| 615 void AppBannerSettingsHelper::SetEngagementWeights(double direct_engagement, |  | 
| 616                                                    double indirect_engagement) { |  | 
| 617   gDirectNavigationEngagement = direct_engagement; |  | 
| 618   gIndirectNavigationEnagagement = indirect_engagement; |  | 
| 619 } |  | 
| 620 |  | 
| 621 void AppBannerSettingsHelper::SetMinimumMinutesBetweenVisits( |  | 
| 622     unsigned int minutes) { |  | 
| 623   gMinimumMinutesBetweenVisits = minutes; |  | 
| 624 } |  | 
| 625 |  | 
| 626 void AppBannerSettingsHelper::SetTotalEngagementToTrigger( | 385 void AppBannerSettingsHelper::SetTotalEngagementToTrigger( | 
| 627     double total_engagement) { | 386     double total_engagement) { | 
| 628   gTotalEngagementToTrigger = total_engagement; | 387   gTotalEngagementToTrigger = total_engagement; | 
| 629 } | 388 } | 
| 630 | 389 | 
| 631 void AppBannerSettingsHelper::SetDefaultParameters() { | 390 void AppBannerSettingsHelper::SetDefaultParameters() { | 
| 632   SetDaysAfterDismissAndIgnoreToTrigger(kMinimumBannerBlockedToBannerShown, |  | 
| 633                                         kMinimumDaysBetweenBannerShows); |  | 
| 634   SetEngagementWeights(kDefaultDirectNavigationEngagement, |  | 
| 635                        kDefaultIndirectNavigationEngagement); |  | 
| 636   SetMinimumMinutesBetweenVisits(kNumberOfMinutesInADay); |  | 
| 637   SetTotalEngagementToTrigger(kDefaultTotalEngagementToTrigger); | 391   SetTotalEngagementToTrigger(kDefaultTotalEngagementToTrigger); | 
| 638 } | 392 } | 
| 639 | 393 | 
| 640 // Given a time, returns that time scoped to the nearest minute resolution |  | 
| 641 // locally. For example, if the resolution is one hour, this function will |  | 
| 642 // return the time to the closest (previous) hour in the local time zone. |  | 
| 643 base::Time AppBannerSettingsHelper::BucketTimeToResolution( |  | 
| 644     base::Time time, |  | 
| 645     unsigned int minutes) { |  | 
| 646   // Only support resolutions smaller than or equal to one day. Enforce |  | 
| 647   // that resolutions divide evenly into one day. Otherwise, default to a |  | 
| 648   // day resolution (each time converted to midnight local time). |  | 
| 649   if (minutes == 0 || minutes >= kNumberOfMinutesInADay || |  | 
| 650       kNumberOfMinutesInADay % minutes != 0) { |  | 
| 651     return time.LocalMidnight(); |  | 
| 652   } |  | 
| 653 |  | 
| 654   // Extract the number of minutes past midnight in local time. Divide that |  | 
| 655   // number by the resolution size, and return the time converted to local |  | 
| 656   // midnight with the resulting truncated number added. |  | 
| 657   base::Time::Exploded exploded; |  | 
| 658   time.LocalExplode(&exploded); |  | 
| 659   int total_minutes = exploded.hour * 60 + exploded.minute; |  | 
| 660 |  | 
| 661   // Use truncating integer division here. |  | 
| 662   return time.LocalMidnight() + |  | 
| 663          base::TimeDelta::FromMinutes((total_minutes / minutes) * minutes); |  | 
| 664 } |  | 
| 665 |  | 
| 666 void AppBannerSettingsHelper::UpdateFromFieldTrial() { | 394 void AppBannerSettingsHelper::UpdateFromFieldTrial() { | 
| 667   // If we are using the site engagement score, only extract the total | 395   // If we are using the site engagement score, only extract the total | 
| 668   // engagement to trigger from the params variations. | 396   // engagement to trigger from the params variations. | 
| 669   UpdateDaysBetweenShowing(); | 397   UpdateDaysBetweenShowing(); | 
| 670   if (ShouldUseSiteEngagementScore()) { | 398   UpdateSiteEngagementToTrigger(); | 
| 671     UpdateSiteEngagementToTrigger(); |  | 
| 672   } else { |  | 
| 673     UpdateEngagementWeights(); |  | 
| 674     UpdateMinutesBetweenVisits(); |  | 
| 675   } |  | 
| 676 } | 399 } | 
| 677 | 400 | 
| 678 AppBannerSettingsHelper::LanguageOption | 401 AppBannerSettingsHelper::LanguageOption | 
| 679 AppBannerSettingsHelper::GetHomescreenLanguageOption() { | 402 AppBannerSettingsHelper::GetHomescreenLanguageOption() { | 
| 680   std::string param = variations::GetVariationParamValue( | 403   std::string param = variations::GetVariationParamValue( | 
| 681       kBannerParamsKey, kBannerParamsLanguageKey); | 404       kBannerParamsKey, kBannerParamsLanguageKey); | 
| 682   unsigned int language_option = 0; | 405   unsigned int language_option = 0; | 
| 683 | 406 | 
| 684   if (param.empty() || !base::StringToUint(param, &language_option) || | 407   if (param.empty() || !base::StringToUint(param, &language_option) || | 
| 685       language_option < LANGUAGE_OPTION_MIN || | 408       language_option < LANGUAGE_OPTION_MIN || | 
| 686       language_option > LANGUAGE_OPTION_MAX) { | 409       language_option > LANGUAGE_OPTION_MAX) { | 
| 687     return LANGUAGE_OPTION_DEFAULT; | 410     return LANGUAGE_OPTION_DEFAULT; | 
| 688   } | 411   } | 
| 689 | 412 | 
| 690   return static_cast<LanguageOption>(language_option); | 413   return static_cast<LanguageOption>(language_option); | 
| 691 } | 414 } | 
| 692 |  | 
| 693 bool AppBannerSettingsHelper::ShouldUseSiteEngagementScore() { |  | 
| 694   if (base::CommandLine::ForCurrentProcess()->HasSwitch( |  | 
| 695           switches::kEnableSiteEngagementAppBanner)) { |  | 
| 696     return true; |  | 
| 697   } |  | 
| 698 |  | 
| 699   // Assume any value which is not "0" or "false" indicates that we should use |  | 
| 700   // site engagement. |  | 
| 701   std::string param = variations::GetVariationParamValue( |  | 
| 702       kBannerParamsKey, kBannerSiteEngagementParamsKey); |  | 
| 703 |  | 
| 704   return (!param.empty() && param != "0" && param != "false"); |  | 
| 705 } |  | 
| OLD | NEW | 
|---|