config.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/history_clusters/core/config.h"
  5. #include "base/containers/contains.h"
  6. #include "base/feature_list.h"
  7. #include "base/metrics/field_trial_params.h"
  8. #include "base/no_destructor.h"
  9. #include "base/strings/string_piece_forward.h"
  10. #include "base/strings/string_split.h"
  11. #include "build/build_config.h"
  12. #include "components/history_clusters/core/features.h"
  13. #include "components/history_clusters/core/history_clusters_prefs.h"
  14. #include "components/history_clusters/core/history_clusters_service.h"
  15. #include "components/history_clusters/core/on_device_clustering_features.h"
  16. #include "components/prefs/pref_service.h"
  17. #include "ui/base/l10n/l10n_util.h"
  18. namespace history_clusters {
  19. namespace {
  20. Config& GetConfigInternal() {
  21. static base::NoDestructor<Config> s_config;
  22. return *s_config;
  23. }
  24. } // namespace
  25. Config::Config() {
  26. // Override any parameters that may be provided by Finch.
  27. is_journeys_enabled_no_locale_check =
  28. base::FeatureList::IsEnabled(internal::kJourneys);
  29. max_visits_to_cluster = base::GetFieldTrialParamByFeatureAsInt(
  30. internal::kJourneys, "JourneysMaxVisitsToCluster", max_visits_to_cluster);
  31. max_keyword_phrases = base::GetFieldTrialParamByFeatureAsInt(
  32. internal::kJourneys, "JourneysMaxKeywordPhrases", max_keyword_phrases);
  33. persist_clusters_in_history_db = base::GetFieldTrialParamByFeatureAsBool(
  34. internal::kJourneys, "JourneysPersistClustersInHistoryDb",
  35. persist_clusters_in_history_db);
  36. persist_clusters_in_history_db_after_startup_delay_minutes =
  37. base::GetFieldTrialParamByFeatureAsInt(
  38. internal::kJourneys,
  39. "JourneysPersistClustersInHistoryDbAfterStartupDelayMinutes",
  40. persist_clusters_in_history_db_after_startup_delay_minutes);
  41. persist_clusters_in_history_db_period_minutes =
  42. base::GetFieldTrialParamByFeatureAsInt(
  43. internal::kJourneys,
  44. "JourneysPersistClustersInHistoryDbPeriodMinutes",
  45. persist_clusters_in_history_db_period_minutes);
  46. min_score_to_always_show_above_the_fold =
  47. base::GetFieldTrialParamByFeatureAsDouble(
  48. internal::kJourneys, "JourneysMinScoreToAlwaysShowAboveTheFold",
  49. min_score_to_always_show_above_the_fold);
  50. num_visits_to_always_show_above_the_fold =
  51. base::GetFieldTrialParamByFeatureAsInt(
  52. internal::kJourneys, "JourneysNumVisitsToAlwaysShowAboveTheFold",
  53. num_visits_to_always_show_above_the_fold);
  54. drop_hidden_visits = base::GetFieldTrialParamByFeatureAsBool(
  55. internal::kJourneys, "drop_hidden_visits", drop_hidden_visits);
  56. rescore_visits_within_clusters_for_query =
  57. base::GetFieldTrialParamByFeatureAsBool(
  58. internal::kJourneys, "JourneysRescoreVisitsWithinClustersForQuery",
  59. rescore_visits_within_clusters_for_query);
  60. sort_clusters_within_batch_for_query =
  61. base::GetFieldTrialParamByFeatureAsBool(
  62. internal::kJourneys, "JourneysSortClustersWithinBatchForQuery",
  63. sort_clusters_within_batch_for_query);
  64. omnibox_action = base::FeatureList::IsEnabled(internal::kOmniboxAction);
  65. omnibox_action_on_urls = base::GetFieldTrialParamByFeatureAsBool(
  66. internal::kOmniboxAction, "omnibox_action_on_urls",
  67. omnibox_action_on_urls);
  68. omnibox_action_on_noisy_urls = base::GetFieldTrialParamByFeatureAsBool(
  69. internal::kOmniboxAction, "omnibox_action_on_noisy_urls",
  70. omnibox_action_on_noisy_urls);
  71. omnibox_action_on_navigation_intents =
  72. base::GetFieldTrialParamByFeatureAsBool(
  73. internal::kOmniboxAction, "omnibox_action_on_navigation_intents",
  74. omnibox_action_on_navigation_intents);
  75. omnibox_action_navigation_intent_score_threshold =
  76. base::GetFieldTrialParamByFeatureAsInt(
  77. internal::kOmniboxAction,
  78. "omnibox_action_on_navigation_intent_score_threshold",
  79. omnibox_action_navigation_intent_score_threshold);
  80. omnibox_action_with_pedals = base::GetFieldTrialParamByFeatureAsBool(
  81. internal::kOmniboxAction, "omnibox_action_with_pedals",
  82. omnibox_action_with_pedals);
  83. omnibox_history_cluster_provider =
  84. base::FeatureList::IsEnabled(internal::kOmniboxHistoryClusterProvider);
  85. keyword_filter_on_entity_aliases = base::GetFieldTrialParamByFeatureAsBool(
  86. history_clusters::features::kOnDeviceClusteringKeywordFiltering,
  87. "keyword_filter_on_entity_aliases", keyword_filter_on_entity_aliases);
  88. max_entity_aliases_in_keywords = base::GetFieldTrialParamByFeatureAsInt(
  89. history_clusters::features::kOnDeviceClusteringKeywordFiltering,
  90. "max_entity_aliases_in_keywords", max_entity_aliases_in_keywords);
  91. if (max_entity_aliases_in_keywords <= 0) {
  92. max_entity_aliases_in_keywords = SIZE_MAX;
  93. }
  94. keyword_filter_on_categories = GetFieldTrialParamByFeatureAsBool(
  95. history_clusters::features::kOnDeviceClusteringKeywordFiltering,
  96. "keyword_filter_on_categories", keyword_filter_on_categories);
  97. keyword_filter_on_noisy_visits = GetFieldTrialParamByFeatureAsBool(
  98. history_clusters::features::kOnDeviceClusteringKeywordFiltering,
  99. "keyword_filter_on_noisy_visits", keyword_filter_on_noisy_visits);
  100. keyword_filter_on_search_terms = GetFieldTrialParamByFeatureAsBool(
  101. history_clusters::features::kOnDeviceClusteringKeywordFiltering,
  102. "keyword_filter_on_search_terms", keyword_filter_on_search_terms);
  103. keyword_filter_on_visit_hosts = GetFieldTrialParamByFeatureAsBool(
  104. history_clusters::features::kOnDeviceClusteringKeywordFiltering,
  105. "keyword_filter_on_visit_hosts", keyword_filter_on_visit_hosts);
  106. category_keyword_score_weight = GetFieldTrialParamByFeatureAsDouble(
  107. features::kOnDeviceClusteringKeywordFiltering,
  108. "category_keyword_score_weight", category_keyword_score_weight);
  109. max_num_keywords_per_cluster = GetFieldTrialParamByFeatureAsInt(
  110. features::kOnDeviceClusteringKeywordFiltering,
  111. "max_num_keywords_per_cluster", max_num_keywords_per_cluster);
  112. non_user_visible_debug =
  113. base::FeatureList::IsEnabled(internal::kNonUserVisibleDebug);
  114. user_visible_debug =
  115. base::FeatureList::IsEnabled(internal::kUserVisibleDebug);
  116. persist_context_annotations_in_history_db = base::FeatureList::IsEnabled(
  117. internal::kPersistContextAnnotationsInHistoryDb);
  118. history_clusters_internals_page =
  119. base::FeatureList::IsEnabled(internal::kHistoryClustersInternalsPage);
  120. cluster_navigation_time_cutoff =
  121. base::Minutes(GetFieldTrialParamByFeatureAsInt(
  122. features::kOnDeviceClustering, "navigation_time_cutoff_minutes",
  123. cluster_navigation_time_cutoff.InMinutes()));
  124. entity_relevance_threshold = GetFieldTrialParamByFeatureAsInt(
  125. features::kOnDeviceClustering, "entity_relevance_threshold",
  126. entity_relevance_threshold);
  127. // Ensure that the value is [0 and 100].
  128. DCHECK_GE(entity_relevance_threshold, 0);
  129. DCHECK_LE(entity_relevance_threshold, 100);
  130. category_relevance_threshold = GetFieldTrialParamByFeatureAsInt(
  131. features::kOnDeviceClustering, "category_relevance_threshold",
  132. category_relevance_threshold);
  133. // Ensure that the value is [0 and 100].
  134. DCHECK_GE(category_relevance_threshold, 0);
  135. DCHECK_LE(category_relevance_threshold, 100);
  136. content_clustering_enabled = GetFieldTrialParamByFeatureAsBool(
  137. features::kOnDeviceClustering, "content_clustering_enabled",
  138. content_clustering_enabled);
  139. content_clustering_entity_similarity_weight =
  140. GetFieldTrialParamByFeatureAsDouble(
  141. features::kOnDeviceClustering,
  142. "content_clustering_entity_similarity_weight",
  143. content_clustering_entity_similarity_weight);
  144. content_clustering_category_similarity_weight =
  145. GetFieldTrialParamByFeatureAsDouble(
  146. features::kOnDeviceClustering,
  147. "content_clustering_category_similarity_weight",
  148. content_clustering_category_similarity_weight);
  149. content_clustering_similarity_threshold = GetFieldTrialParamByFeatureAsDouble(
  150. features::kOnDeviceClustering, "content_clustering_similarity_threshold",
  151. content_clustering_similarity_threshold);
  152. // Ensure that the value is [0.0 and 1.0].
  153. DCHECK_GE(content_clustering_similarity_threshold, 0.0f);
  154. DCHECK_LE(content_clustering_similarity_threshold, 1.0f);
  155. content_visibility_threshold = GetFieldTrialParamByFeatureAsDouble(
  156. features::kOnDeviceClustering, "content_visibility_threshold", 0.7);
  157. // Ensure that the value is [0.0 and 1.0].
  158. DCHECK_GE(content_visibility_threshold, 0.0f);
  159. DCHECK_LE(content_visibility_threshold, 1.0f);
  160. should_hide_single_visit_clusters_on_prominent_ui_surfaces =
  161. GetFieldTrialParamByFeatureAsBool(
  162. features::kOnDeviceClustering,
  163. "hide_single_visit_clusters_on_prominent_ui_surfaces",
  164. should_hide_single_visit_clusters_on_prominent_ui_surfaces);
  165. should_hide_single_domain_clusters_on_prominent_ui_surfaces =
  166. GetFieldTrialParamByFeatureAsBool(
  167. features::kOnDeviceClustering,
  168. "hide_single_domain_clusters_on_prominent_ui_surfaces",
  169. should_hide_single_domain_clusters_on_prominent_ui_surfaces);
  170. should_filter_noisy_clusters = GetFieldTrialParamByFeatureAsBool(
  171. features::kOnDeviceClustering, "filter_noisy_clusters",
  172. should_filter_noisy_clusters);
  173. noisy_cluster_visits_engagement_threshold =
  174. GetFieldTrialParamByFeatureAsDouble(
  175. features::kOnDeviceClustering,
  176. "noisy_cluster_visit_engagement_threshold",
  177. noisy_cluster_visits_engagement_threshold);
  178. number_interesting_visits_filter_threshold = GetFieldTrialParamByFeatureAsInt(
  179. features::kOnDeviceClustering, "num_interesting_visits_filter_threshold",
  180. number_interesting_visits_filter_threshold);
  181. visit_duration_ranking_weight = GetFieldTrialParamByFeatureAsDouble(
  182. features::kOnDeviceClustering, "visit_duration_ranking_weight",
  183. visit_duration_ranking_weight);
  184. DCHECK_GE(visit_duration_ranking_weight, 0.0f);
  185. foreground_duration_ranking_weight = GetFieldTrialParamByFeatureAsDouble(
  186. features::kOnDeviceClustering, "foreground_duration_ranking_weight",
  187. foreground_duration_ranking_weight);
  188. DCHECK_GE(foreground_duration_ranking_weight, 0.0f);
  189. bookmark_ranking_weight = GetFieldTrialParamByFeatureAsDouble(
  190. features::kOnDeviceClustering, "bookmark_ranking_weight",
  191. bookmark_ranking_weight);
  192. DCHECK_GE(bookmark_ranking_weight, 0.0f);
  193. search_results_page_ranking_weight = GetFieldTrialParamByFeatureAsDouble(
  194. features::kOnDeviceClustering, "search_results_page_ranking_weight",
  195. search_results_page_ranking_weight);
  196. DCHECK_GE(search_results_page_ranking_weight, 0.0f);
  197. has_page_title_ranking_weight = GetFieldTrialParamByFeatureAsDouble(
  198. features::kOnDeviceClustering, "has_page_title_ranking_weight",
  199. has_page_title_ranking_weight);
  200. DCHECK_GE(has_page_title_ranking_weight, 0.0f);
  201. content_cluster_on_intersection_similarity =
  202. GetFieldTrialParamByFeatureAsBool(
  203. features::kOnDeviceClustering,
  204. "use_content_clustering_intersection_similarity",
  205. content_cluster_on_intersection_similarity);
  206. cluster_interaction_threshold = GetFieldTrialParamByFeatureAsInt(
  207. features::kOnDeviceClustering,
  208. "content_clustering_intersection_threshold",
  209. cluster_interaction_threshold);
  210. split_clusters_at_search_visits = GetFieldTrialParamByFeatureAsBool(
  211. features::kOnDeviceClustering, "split_clusters_at_search_visits",
  212. split_clusters_at_search_visits);
  213. should_label_clusters =
  214. base::FeatureList::IsEnabled(internal::kJourneysLabels);
  215. labels_from_hostnames = GetFieldTrialParamByFeatureAsBool(
  216. internal::kJourneysLabels, "labels_from_hostnames",
  217. labels_from_hostnames);
  218. labels_from_entities = GetFieldTrialParamByFeatureAsBool(
  219. internal::kJourneysLabels, "labels_from_entities", labels_from_entities);
  220. should_check_hosts_to_skip_clustering_for =
  221. base::FeatureList::IsEnabled(features::kOnDeviceClusteringBlocklists);
  222. engagement_score_cache_size = GetFieldTrialParamByFeatureAsInt(
  223. features::kUseEngagementScoreCache, "engagement_score_cache_size",
  224. engagement_score_cache_size);
  225. engagement_score_cache_refresh_duration =
  226. base::Minutes(GetFieldTrialParamByFeatureAsInt(
  227. features::kUseEngagementScoreCache,
  228. "engagement_score_cache_refresh_duration_minutes",
  229. engagement_score_cache_refresh_duration.InMinutes()));
  230. use_continue_on_shutdown = base::FeatureList::IsEnabled(
  231. internal::kHistoryClustersUseContinueOnShutdown);
  232. }
  233. Config::Config(const Config& other) = default;
  234. Config::~Config() = default;
  235. void SetConfigForTesting(const Config& config) {
  236. GetConfigInternal() = config;
  237. }
  238. base::flat_set<std::string> JourneysMidBlocklist() {
  239. const base::FeatureParam<std::string> kJourneysMidBlocklist{
  240. &internal::kHistoryClustersKeywordFiltering, "JourneysMidBlocklist", ""};
  241. std::string blocklist_string = kJourneysMidBlocklist.Get();
  242. if (blocklist_string.empty())
  243. return {};
  244. auto blocklist = base::SplitString(blocklist_string, ",",
  245. base::WhitespaceHandling::TRIM_WHITESPACE,
  246. base::SplitResult::SPLIT_WANT_NONEMPTY);
  247. return blocklist.empty()
  248. ? base::flat_set<std::string>()
  249. : base::flat_set<std::string>(blocklist.begin(), blocklist.end());
  250. }
  251. bool IsApplicationLocaleSupportedByJourneys(
  252. const std::string& application_locale) {
  253. // Application locale support should be checked only if the Journeys feature
  254. // is enabled.
  255. DCHECK(GetConfig().is_journeys_enabled_no_locale_check);
  256. // Note, we now set a default value for the allowlist, which means that when
  257. // the feature parameter is undefined, the below allowlist is enabled.
  258. const base::FeatureParam<std::string> kLocaleOrLanguageAllowlist{
  259. &internal::kJourneys, "JourneysLocaleOrLanguageAllowlist",
  260. "de:en:es:fr:it:nl:pt:tr"};
  261. // To allow for using any locale, we also interpret the special '*' value.
  262. auto allowlist_string = kLocaleOrLanguageAllowlist.Get();
  263. if (allowlist_string == "*")
  264. return true;
  265. // Allow comma and colon as delimiters to the language list.
  266. auto allowlist = base::SplitString(
  267. allowlist_string, ",:", base::WhitespaceHandling::TRIM_WHITESPACE,
  268. base::SplitResult::SPLIT_WANT_NONEMPTY);
  269. // Allow any exact locale matches, and also allow any users where the
  270. // primary language subtag, e.g. "en" from "en-US" to match any element of
  271. // the list.
  272. return allowlist.empty() || base::Contains(allowlist, application_locale) ||
  273. base::Contains(allowlist, l10n_util::GetLanguage(application_locale));
  274. }
  275. bool IsJourneysEnabledInOmnibox(HistoryClustersService* service,
  276. PrefService* prefs) {
  277. if (!service)
  278. return false;
  279. if (!service->IsJourneysEnabled())
  280. return false;
  281. if (!prefs->GetBoolean(history_clusters::prefs::kVisible))
  282. return false;
  283. return true;
  284. }
  285. const Config& GetConfig() {
  286. return GetConfigInternal();
  287. }
  288. } // namespace history_clusters