blob: a70080ae8b5d3100427e35f0a5d454607ec89a1f [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "survey_config.h"
#include <optional>
#include <vector>
#include "base/check.h"
#include "base/feature_list.h"
#include "base/features.h"
#include "base/strings/string_util.h"
#include "chrome/browser/metrics/variations/google_groups_manager_factory.h"
#include "chrome/browser/privacy_sandbox/incognito/privacy_sandbox_incognito_features.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/lens/lens_features.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "components/page_info/core/features.h"
#include "components/permissions/features.h"
#include "components/permissions/permission_hats_trigger_helper.h"
#include "components/plus_addresses/core/browser/plus_address_hats_utils.h"
#include "components/plus_addresses/core/common/features.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/signin/public/base/signin_switches.h"
#include "components/variations/service/google_groups_manager.h"
#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/download/download_warning_desktop_hats_utils.h"
#include "components/password_manager/core/browser/features/password_features.h" // nogncheck
#include "components/password_manager/core/browser/features/password_manager_features_util.h" // nogncheck
#include "components/performance_manager/public/features.h" // nogncheck
#include "components/permissions/constants.h" // nogncheck
#include "components/safe_browsing/core/common/features.h" // nogncheck
#include "components/safe_browsing/core/common/safebrowsing_constants.h" // nogncheck
#else
#include "chrome/browser/flags/android/chrome_feature_list.h"
#endif // #if !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(ENABLE_COMPOSE)
#include "components/compose/core/browser/compose_features.h"
#endif // #if !BUILDFLAG(ENABLE_COMPOSE)
#if !BUILDFLAG(IS_ANDROID)
constexpr char kHatsSurveyTriggerAutofillAddress[] = "autofill-address";
constexpr char kHatsSurveyTriggerAutofillAddressUserPerception[] =
"autofill-address-users-perception";
constexpr char kHatsSurveyTriggerAutofillAddressUserDeclinedSuggestion[] =
"autofill-address-users-perception";
constexpr char kHatsSurveyTriggerAutofillAddressUserDeclinedSave[] =
"autofill-address-user-declined-save";
constexpr char kHatsSurveyTriggerAutofillCreditCardUserPerception[] =
"autofill-credit-card-users-perception";
constexpr char kHatsSurveyTriggerAutofillPasswordUserPerception[] =
"autofill-password-users-perception";
constexpr char kHatsSurveyTriggerAutofillCard[] = "autofill-card";
constexpr char kHatsSurveyTriggerAutofillPassword[] = "autofill-password";
constexpr char kHatsSurveyTriggerDownloadWarningBubbleBypass[] =
"download-warning-bubble-bypass";
constexpr char kHatsSurveyTriggerDownloadWarningBubbleHeed[] =
"download-warning-bubble-heed";
constexpr char kHatsSurveyTriggerDownloadWarningBubbleIgnore[] =
"download-warning-bubble-ignore";
constexpr char kHatsSurveyTriggerDownloadWarningPageBypass[] =
"download-warning-page-bypass";
constexpr char kHatsSurveyTriggerDownloadWarningPageHeed[] =
"download-warning-page-heed";
constexpr char kHatsSurveyTriggerDownloadWarningPageIgnore[] =
"download-warning-page-ignore";
constexpr char kHatsSurveyTriggerHistoryEmbeddings[] = "history-embeddings";
constexpr char kHatsSurveyTriggerIdentityAddressBubbleSignin[] =
"identity-address-bubble-signin";
constexpr char kHatsSurveyTriggerIdentityDiceWebSigninAccepted[] =
"identity-dice-web-signin-accepted";
constexpr char kHatsSurveyTriggerIdentityDiceWebSigninDeclined[] =
"identity-dice-web-signin-declined";
constexpr char kHatsSurveyTriggerIdentityFirstRunSignin[] =
"identity-first-run-signin";
constexpr char kHatsSurveyTriggerIdentityPasswordBubbleSignin[] =
"identity-password-bubble-signin";
constexpr char kHatsSurveyTriggerIdentityProfileMenuDismissed[] =
"identity-profile-menu-dismissed";
constexpr char kHatsSurveyTriggerIdentityProfileMenuSignin[] =
"identity-profile-menu-signin";
constexpr char kHatsSurveyTriggerIdentityProfilePickerAddProfileSignin[] =
"identity-profile-picker-add-profile-signin";
constexpr char kHatsSurveyTriggerIdentitySigninInterceptProfileSeparation[] =
"identity-signin-intercept-profile-separation";
constexpr char kHatsSurveyTriggerIdentitySigninPromoBubbleDismissed[] =
"identity-signin-promo-bubble-dismissed";
constexpr char kHatsSurveyTriggerIdentitySwitchProfileFromProfileMenu[] =
"identity-switch-profile-profile-menu";
constexpr char kHatsSurveyTriggerIdentitySwitchProfileFromProfilePicker[] =
"identity-switch-profile-profile-picker";
constexpr char kHatsSurveyTriggerLensOverlayResults[] = "lens-overlay-results";
constexpr char kHatsSurveyTriggerNtpModules[] = "ntp-modules";
constexpr char kHatsSurveyTriggerNtpPhotosModuleOptOut[] =
"ntp-photos-module-opt-out";
constexpr char kHatsSurveyTriggerPasswordChangeCanceled[] =
"password-change-canceled";
constexpr char kHatsSurveyTriggerPasswordChangeDelayed[] =
"password-change-delayed";
constexpr char kHatsSurveyTriggerPasswordChangeError[] =
"password-change-error";
constexpr char kHatsSurveyTriggerPasswordChangeSuccess[] =
"password-change-success";
constexpr char kHatsSurveyTriggerPerformanceControlsPPM[] = "performance-ppm";
// The permission prompt trigger permits configuring multiple triggers
// simultaneously. Each trigger increments a counter at the end -->
// "permission-prompt0", "permission-prompt1", ...
constexpr char kHatsSurveyTriggerPrivacyGuide[] = "privacy-guide";
constexpr char kHatsSurveyTriggerRedWarning[] = "red-warning";
constexpr char kHatsSurveyTriggerSafetyHubOneOffExperimentControl[] =
"safety-hub-control";
constexpr char kHatsSurveyTriggerSafetyHubOneOffExperimentNotification[] =
"safety-hub-notification";
constexpr char kHatsSurveyTriggerSafetyHubOneOffExperimentInteraction[] =
"safety-hub-interaction";
constexpr char kHatsSurveyTriggerSettings[] = "settings";
constexpr char kHatsSurveyTriggerSettingsPrivacy[] = "settings-privacy";
constexpr char kHatsSurveyTriggerSettingsSecurity[] = "settings-security";
constexpr char kHatsSurveyTriggerTrustSafetyPrivacySettings[] =
"ts-privacy-settings";
constexpr char kHatsSurveyTriggerTrustSafetyTrustedSurface[] =
"ts-trusted-surface";
constexpr char kHatsSurveyTriggerTrustSafetyTransactions[] = "ts-transactions";
constexpr char kHatsSurveyTriggerWhatsNew[] = "whats-new";
constexpr char kHatsSurveyTriggerTrustSafetyV2BrowsingData[] =
"ts-v2-browsing-data";
constexpr char kHatsSurveyTriggerTrustSafetyV2ControlGroup[] =
"ts-v2-control-group";
constexpr char kHatsSurveyTriggerTrustSafetyV2DownloadWarningUI[] =
"ts-v2-download-warning-ui";
constexpr char kHatsSurveyTriggerTrustSafetyV2PasswordCheck[] =
"ts-v2-password-check";
constexpr char kHatsSurveyTriggerTrustSafetyV2PasswordProtectionUI[] =
"ts-v2-password-protection-ui";
constexpr char kHatsSurveyTriggerTrustSafetyV2SafetyCheck[] =
"ts-v2-safety-check";
constexpr char kHatsSurveyTriggerTrustSafetyV2SafetyHubNotification[] =
"ts-v2-safety-hub-notification";
constexpr char kHatsSurveyTriggerTrustSafetyV2SafetyHubInteraction[] =
"ts-v2-safety-hub-interaction";
constexpr char kHatsSurveyTriggerTrustSafetyV2TrustedSurface[] =
"ts-v2-trusted-surface";
constexpr char kHatsSurveyTriggerTrustSafetyV2PrivacyGuide[] =
"ts-v2-privacy-guide";
constexpr char kHatsSurveyTriggerTrustSafetyV2SafeBrowsingInterstitial[] =
"ts-v2-safe-browsing-interstitial";
constexpr char kHatsSurveyTriggerWallpaperSearch[] = "wallpaper-search";
#else // BUILDFLAG(IS_ANDROID)
constexpr char kHatsSurveyTriggerAndroidStartupSurvey[] = "startup_survey";
constexpr char kHatsSurveyTriggerQuickDelete[] = "quick_delete_survey";
constexpr char kHatsSurveyTriggerClearBrowsingData[] =
"clear_browsing_data_survey";
constexpr char kHatsSurveyTriggerSafetyHubAndroid[] =
"safety_hub_android_survey";
constexpr char kHatsSurveyOrganicTriggerSafetyHubAndroid[] =
"safety_hub_android_organic_survey";
#endif // #if !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
constexpr char kHatsSurveyTriggerPrivacySandboxWhatsNewSurvey[] =
"privacy-sandbox-whats-new-survey";
#endif // !BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
#if BUILDFLAG(ENABLE_COMPOSE)
constexpr char kHatsSurveyTriggerComposeAcceptance[] = "compose-acceptance";
constexpr char kHatsSurveyTriggerComposeClose[] = "compose-close";
constexpr char kHatsSurveyTriggerComposeNudgeClose[] = "compose-nudge-close";
#endif // BUILDFLAG(ENABLE_COMPOSE)
constexpr char kHatsHistogramPrefix[] = "Feedback.HappinessTrackingSurvey.";
constexpr char kHatsSurveyTriggerTesting[] = "testing";
constexpr char kHatsNextSurveyTriggerIDTesting[] =
"HLpeYy5Av0ugnJ3q1cK0XzzA8UHv";
constexpr char kHatsSurveyTriggerPermissionsPrompt[] = "permissions-prompt";
constexpr char kHatsSurveyTriggerPlusAddressAcceptedFirstTimeCreate[] =
"plus-address-accepted-first-time-create";
constexpr char kHatsSurveyTriggerPlusAddressCreatedMultiplePlusAddresses[] =
"plus-address-created-multiple-plus_addresses";
constexpr char
kHatsSurveyTriggerPlusAddressCreatedPlusAddressViaManualFallback[] =
"plus-address-created-plus-address-via-manual-fallback";
constexpr char kHatsSurveyTriggerPlusAddressDeclinedFirstTimeCreate[] =
"plus-address-declined-first-time-create";
constexpr char
kHatsSurveyTriggerPlusAddressDidChooseEmailOverPlusAddressSurvey[] =
"plus-address-did-choose-email-over-plus-address";
constexpr char
kHatsSurveyTriggerPlusAddressDidChoosePlusAddressOverEmailSurvey[] =
"plus-address-did-choose-plus-address-over-email";
constexpr char
kHatsSurveyTriggerPlusAddressFilledPlusAddressViaManualFallback[] =
"plus-address-filled-plus-address-via-manual-fallback";
constexpr char kHatsSurveyTriggerPrivacySandboxSentimentSurvey[] =
"privacy-sandbox-sentiment-survey";
constexpr char kHatsSurveyTriggerPrivacySandboxActSurvey[] =
"privacy-sandbox-act-survey";
constexpr char kHatsSurveyTriggerMerchantTrustEvaluationControlSurvey[] =
"merchant-trust-evaluation-control-survey";
constexpr char kHatsSurveyTriggerMerchantTrustEvaluationExperimentSurvey[] =
"merchant-trust-evaluation-experiment-survey";
constexpr char kHatsSurveyTriggerMerchantTrustLearnSurvey[] =
"merchant-trust-learn-survey";
constexpr char kHatsSurveyTriggerOnFocusZpsSuggestionsHappiness[] =
"omnibox-on-focus-happiness";
constexpr char kHatsSurveyTriggerOnFocusZpsSuggestionsUtility[] =
"omnibox-on-focus-utility";
namespace {
constexpr char kHatsSurveyProbability[] = "probability";
constexpr char kHatsSurveyEnSiteID[] = "en_site_id";
constexpr char kHatsSurveyHistogramName[] = "hats_histogram_name";
constexpr char kHatsSurveyUkmId[] = "hats_survey_ukm_id";
constexpr double kHatsSurveyProbabilityDefault = 0;
// Survey configs must always be hardcoded here, so that they require review
// from HaTS owners. Do not move this method out of the anonymous namespace or
// change its signature to work around this.
std::vector<hats::SurveyConfig> GetAllSurveyConfigs() {
std::vector<hats::SurveyConfig> survey_configs;
// Always add the default survey.
hats::SurveyConfig default_survey;
default_survey.enabled = true;
default_survey.probability = 1.0f;
default_survey.trigger = kHatsSurveyTriggerTesting;
default_survey.trigger_id = kHatsNextSurveyTriggerIDTesting;
default_survey.product_specific_bits_data_fields = {"Test Field 1",
"Test Field 2"};
default_survey.product_specific_string_data_fields = {"Test Field 3"};
survey_configs.emplace_back(default_survey);
// Permission prompt survey
survey_configs.emplace_back(
&permissions::features::kPermissionsPromptSurvey,
kHatsSurveyTriggerPermissionsPrompt,
/*presupplied_trigger_id=*/std::nullopt,
std::vector<std::string>{
permissions::kPermissionsPromptSurveyHadGestureKey},
std::vector<std::string>{
permissions::kPermissionsPromptSurveyPromptDispositionKey,
permissions::kPermissionsPromptSurveyPromptDispositionReasonKey,
permissions::kPermissionsPromptSurveyActionKey,
permissions::kPermissionsPromptSurveyRequestTypeKey,
permissions::kPermissionsPromptSurveyReleaseChannelKey,
permissions::kPermissionsPromptSurveyDisplayTimeKey,
permissions::kPermissionPromptSurveyOneTimePromptsDecidedBucketKey,
permissions::kPermissionPromptSurveyUrlKey,
permissions::kPermissionPromptSurveyPepcPromptPositionKey,
permissions::kPermissionPromptSurveyInitialPermissionStatusKey,
permissions::kPermissionPromptSurveyPromptOptionsKey,
permissions::kPermissionPromptSurveyPromptDisplayDurationKey});
// Privacy sandbox always on sentiment survey
survey_configs.emplace_back(
&privacy_sandbox::kPrivacySandboxSentimentSurvey,
kHatsSurveyTriggerPrivacySandboxSentimentSurvey,
privacy_sandbox::kPrivacySandboxSentimentSurveyTriggerId.Get(),
/*product_specific_bits_data_fields=*/
std::vector<std::string>{"Topics enabled", "Protected audience enabled",
"Measurement enabled", "Signed in"},
/*product_specific_string_data_fields=*/
std::vector<std::string>{"Channel"},
/*log_responses_to_uma=*/true,
/*log_responses_to_ukm=*/true);
// Privacy sandbox ACT survey
survey_configs.emplace_back( //
&privacy_sandbox::kPrivacySandboxActSurvey,
kHatsSurveyTriggerPrivacySandboxActSurvey,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/
std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{"Survey Trigger Delay"},
/*log_responses_to_uma=*/false,
/*log_responses_to_ukm=*/false,
/*requested_browser_type=*/
hats::SurveyConfig::RequestedBrowserType::kIncognito);
#if !BUILDFLAG(IS_ANDROID)
// Dev tools surveys.
survey_configs.emplace_back(&features::kHaTSDesktopDevToolsIssuesCOEP,
"devtools-issues-coep",
"1DbEs89FS0ugnJ3q1cK0Nx6T99yT");
survey_configs.emplace_back(&features::kHaTSDesktopDevToolsIssuesMixedContent,
"devtools-issues-mixed-content",
"BhCYpUmyf0ugnJ3q1cK0VtxCftzo");
survey_configs.emplace_back(
&features::
kHappinessTrackingSurveysForDesktopDevToolsIssuesCookiesSameSite,
"devtools-issues-cookies-samesite", "w9JqqpmEr0ugnJ3q1cK0NezVg4iK");
survey_configs.emplace_back(&features::kHaTSDesktopDevToolsIssuesHeavyAd,
"devtools-issues-heavy-ad",
"bAeiT5J4P0ugnJ3q1cK0Ra6jg7s8");
survey_configs.emplace_back(&features::kHaTSDesktopDevToolsIssuesCSP,
"devtools-issues-csp",
"c9fjDmwjb0ugnJ3q1cK0USeAJJ9C");
// Settings surveys.
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForDesktopSettings,
kHatsSurveyTriggerSettings);
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForDesktopSettingsPrivacy,
kHatsSurveyTriggerSettingsPrivacy,
/*presupplied_trigger_id=*/std::nullopt,
std::vector<std::string>{"3P cookies blocked"});
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForSecurityPage,
kHatsSurveyTriggerSettingsSecurity,
/*presupplied_trigger_id=*/
features::kHappinessTrackingSurveysForSecurityPageTriggerId.Get(),
std::vector<std::string>{},
std::vector<std::string>{"Security Page User Action",
"Safe Browsing Setting Before Trigger",
"Safe Browsing Setting After Trigger",
"Client Channel", "Time On Page"});
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForDesktopPrivacyGuide,
kHatsSurveyTriggerPrivacyGuide);
// NTP modules survey.
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForDesktopNtpModules,
kHatsSurveyTriggerNtpModules);
// History embeddings survey.
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForHistoryEmbeddings,
kHatsSurveyTriggerHistoryEmbeddings,
/*presupplied_trigger_id=*/std::nullopt,
std::vector<std::string>{"non empty results",
"best matches result clicked", "result clicked",
"answer shown", "answer citation clicked"},
std::vector<std::string>{"query word count"});
// NTP Photos module opt-out survey.
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForNtpPhotosOptOut,
kHatsSurveyTriggerNtpPhotosModuleOptOut);
// Trust & Safety Sentiment surveys.
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurvey,
kHatsSurveyTriggerTrustSafetyPrivacySettings,
features::kTrustSafetySentimentSurveyPrivacySettingsTriggerId.Get(),
std::vector<std::string>{"Non default setting", "Ran safety check"});
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurvey,
kHatsSurveyTriggerTrustSafetyTrustedSurface,
features::kTrustSafetySentimentSurveyTrustedSurfaceTriggerId.Get(),
std::vector<std::string>{"Interacted with Page Info"});
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurvey,
kHatsSurveyTriggerTrustSafetyTransactions,
features::kTrustSafetySentimentSurveyTransactionsTriggerId.Get(),
std::vector<std::string>{"Saved password"});
// Trust & Safety Sentiment surveys - Version 2.
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2BrowsingData,
features::kTrustSafetySentimentSurveyV2BrowsingDataTriggerId.Get(),
std::vector<std::string>{"Deleted history", "Deleted downloads",
"Deleted autofill form data"});
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2ControlGroup,
features::kTrustSafetySentimentSurveyV2ControlGroupTriggerId.Get());
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2DownloadWarningUI,
features::kTrustSafetySentimentSurveyV2DownloadWarningUITriggerId.Get(),
std::vector<std::string>{"Enhanced protection enabled", "Is mainpage UI",
"Is subpage UI", "Is downloads page UI",
"Is download prompt UI",
"User proceeded past warning"});
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2PasswordCheck,
features::kTrustSafetySentimentSurveyV2PasswordCheckTriggerId.Get());
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2PasswordProtectionUI,
features::kTrustSafetySentimentSurveyV2PasswordProtectionUITriggerId
.Get(),
std::vector<std::string>{
"Enhanced protection enabled", "Is page info UI",
"Is modal dialog UI", "Is interstitial UI",
"User completed password change", "User clicked change password",
"User ignored warning", "User marked as legitimate"});
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2SafetyCheck,
features::kTrustSafetySentimentSurveyV2SafetyCheckTriggerId.Get());
std::vector<std::string> sh_psd_fields{
"User visited Safety Hub page",
"User clicked Safety Hub notification",
"User interacted with Safety Hub",
"Is notification module extensions",
"Is notification module notification permissions",
"Is notification module passwords",
"Is notification module revoked permissions",
"Is notification module safe browsing",
"Global state is safe",
"Global state is info",
"Global state is warning",
"Global state is weak"};
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2SafetyHubInteraction,
features::kTrustSafetySentimentSurveyV2SafetyHubInteractionTriggerId
.Get(),
sh_psd_fields);
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2SafetyHubNotification,
features::kTrustSafetySentimentSurveyV2SafetyHubNotificationTriggerId
.Get(),
sh_psd_fields);
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2TrustedSurface,
features::kTrustSafetySentimentSurveyV2TrustedSurfaceTriggerId.Get(),
std::vector<std::string>{"Interacted with Page Info"});
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2PrivacyGuide,
features::kTrustSafetySentimentSurveyV2PrivacyGuideTriggerId.Get());
survey_configs.emplace_back(
&features::kTrustSafetySentimentSurveyV2,
kHatsSurveyTriggerTrustSafetyV2SafeBrowsingInterstitial,
features::kTrustSafetySentimentSurveyV2SafeBrowsingInterstitialTriggerId
.Get(),
std::vector<std::string>{
"User proceeded past interstitial", "Enhanced protection enabled",
"Threat is phishing", "Threat is malware",
"Threat is unwanted software", "Threat is billing"});
// Autofill surveys.
survey_configs.emplace_back(
&::autofill::features::kAutofillAddressUserPerceptionSurvey,
kHatsSurveyTriggerAutofillAddressUserPerception, std::nullopt,
std::vector<std::string>{},
std::vector<std::string>{
"Accepted fields", "Corrected to same type",
"Corrected to a different type", "Corrected to an unknown type",
"Corrected to empty", "Manually filled to same type",
"Manually filled to a different type",
"Manually filled to an unknown type", "Total corrected",
"Total filled", "Total unfilled", "Total manually filled",
"Total number of fields"});
survey_configs.emplace_back(
&::autofill::features::kAutofillAddressUserDeclinedSuggestionSurvey,
kHatsSurveyTriggerAutofillAddressUserDeclinedSuggestion, std::nullopt);
survey_configs.emplace_back(
&::autofill::features::kAutofillAddressUserDeclinedSaveSurvey,
kHatsSurveyTriggerAutofillAddressUserDeclinedSave);
survey_configs.emplace_back(
&::autofill::features::kAutofillCreditCardUserPerceptionSurvey,
kHatsSurveyTriggerAutofillCreditCardUserPerception, std::nullopt,
std::vector<std::string>{},
std::vector<std::string>{
"Accepted fields", "Corrected to same type",
"Corrected to a different type", "Corrected to an unknown type",
"Corrected to empty", "Manually filled to same type",
"Manually filled to a different type",
"Manually filled to an unknown type", "Total corrected",
"Total filled", "Total unfilled", "Total manually filled",
"Total number of fields"});
survey_configs.emplace_back(
&password_manager::features::kAutofillPasswordUserPerceptionSurvey,
kHatsSurveyTriggerAutofillPasswordUserPerception, std::nullopt,
std::vector<std::string>{},
std::vector<std::string>{"Filling assistance"});
survey_configs.emplace_back(&features::kAutofillAddressSurvey,
kHatsSurveyTriggerAutofillAddress);
survey_configs.emplace_back(&features::kAutofillCardSurvey,
kHatsSurveyTriggerAutofillCard);
survey_configs.emplace_back(&features::kAutofillPasswordSurvey,
kHatsSurveyTriggerAutofillPassword);
// Wallpaper Search survey.
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForWallpaperSearch,
kHatsSurveyTriggerWallpaperSearch);
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
std::vector<std::string> identity_string_psd_fields{
"Channel", "Chrome Version", "Number of Chrome Profiles",
"Number of Google Accounts", "Sign-in Status"};
survey_configs.emplace_back(
&switches::kChromeIdentitySurveyAddressBubbleSignin,
kHatsSurveyTriggerIdentityAddressBubbleSignin, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveyDiceWebSigninAccepted,
kHatsSurveyTriggerIdentityDiceWebSigninAccepted, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveyDiceWebSigninDeclined,
kHatsSurveyTriggerIdentityDiceWebSigninDeclined, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
survey_configs.emplace_back(&switches::kChromeIdentitySurveyFirstRunSignin,
kHatsSurveyTriggerIdentityFirstRunSignin,
std::nullopt, std::vector<std::string>{},
identity_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveyPasswordBubbleSignin,
kHatsSurveyTriggerIdentityPasswordBubbleSignin, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveyProfileMenuDismissed,
kHatsSurveyTriggerIdentityProfileMenuDismissed, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
survey_configs.emplace_back(&switches::kChromeIdentitySurveyProfileMenuSignin,
kHatsSurveyTriggerIdentityProfileMenuSignin,
std::nullopt, std::vector<std::string>{},
identity_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveyProfilePickerAddProfileSignin,
kHatsSurveyTriggerIdentityProfilePickerAddProfileSignin, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveySigninInterceptProfileSeparation,
kHatsSurveyTriggerIdentitySigninInterceptProfileSeparation, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
std::vector<std::string> identity_dismissed_signin_bubble_string_psd_fields{
"Channel",
"Chrome Version",
"Number of Chrome Profiles",
"Number of Google Accounts",
"Data type Sign-in Bubble Dismissed",
"Sign-in Status"};
survey_configs.emplace_back(
&switches::kChromeIdentitySurveySigninPromoBubbleDismissed,
kHatsSurveyTriggerIdentitySigninPromoBubbleDismissed, std::nullopt,
std::vector<std::string>{},
identity_dismissed_signin_bubble_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveySwitchProfileFromProfileMenu,
kHatsSurveyTriggerIdentitySwitchProfileFromProfileMenu, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
survey_configs.emplace_back(
&switches::kChromeIdentitySurveySwitchProfileFromProfilePicker,
kHatsSurveyTriggerIdentitySwitchProfileFromProfilePicker, std::nullopt,
std::vector<std::string>{}, identity_string_psd_fields);
// Privacy sandbox What's New survey
survey_configs.emplace_back( //
&privacy_sandbox::kPrivacySandboxWhatsNewSurvey,
kHatsSurveyTriggerPrivacySandboxWhatsNewSurvey,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/
std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{"What's New Scroll Depth"}),
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
#if BUILDFLAG(ENABLE_COMPOSE)
// Compose surveys.
survey_configs.emplace_back(
&compose::features::kHappinessTrackingSurveysForComposeAcceptance,
kHatsSurveyTriggerComposeAcceptance,
/*presupplied_trigger_id=*/std::nullopt,
std::vector<std::string>{
"Session used a modifier, like elaborate or formal",
"A safety filter edited a response in this session",
"Any error appeared in this session",
"This session started with nudge"},
std::vector<std::string>{
"Execution ID linked to your recent input and page context", "Url",
"Locale"});
survey_configs.emplace_back(
&compose::features::kHappinessTrackingSurveysForComposeClose,
kHatsSurveyTriggerComposeClose,
/*presupplied_trigger_id=*/std::nullopt,
std::vector<std::string>{
"Session used a modifier, like elaborate or formal",
"A safety filter edited a response in this session",
"Any error appeared in this session",
"This session started with nudge"},
std::vector<std::string>{
"Execution ID linked to your recent input and page context", "Url",
"Locale"});
survey_configs.emplace_back(
&compose::features::kHappinessTrackingSurveysForComposeNudgeClose,
kHatsSurveyTriggerComposeNudgeClose);
#endif // BUILDFLAG(ENABLE_COMPOSE)
// What's New survey.2
survey_configs.emplace_back(
&features::kHappinessTrackingSurveysForDesktopWhatsNew,
kHatsSurveyTriggerWhatsNew);
// Performance Controls surveys.
survey_configs.emplace_back(
&performance_manager::features::kPerformanceControlsPPMSurvey,
kHatsSurveyTriggerPerformanceControlsPPM,
/*presupplied_trigger_id=*/std::nullopt,
std::vector<std::string>{"Memory Saver Mode Enabled",
"Battery Saver Mode Enabled",
"Selected for Uniform Sample"},
std::vector<std::string>{
"Channel",
// Note memory is reported as a range, eg. "Windows, 4 to 8 GB".
"Performance Characteristics (OS and Total Memory)"},
/*log_responses_to_uma=*/true,
/*log_responses_to_ukm=*/true);
// Red Warning surveys.
survey_configs.emplace_back(
&safe_browsing::kRedWarningSurvey, kHatsSurveyTriggerRedWarning,
safe_browsing::kRedWarningSurveyTriggerId.Get(),
std::vector<std::string>{},
std::vector<std::string>{
safe_browsing::kFlaggedUrl, safe_browsing::kMainFrameUrl,
safe_browsing::kReferrerUrl, safe_browsing::kUserActivityWithUrls});
// Desktop download warning surveys.
survey_configs.emplace_back(
&safe_browsing::kDownloadWarningSurvey,
kHatsSurveyTriggerDownloadWarningBubbleBypass,
/*presupplied_trigger_id=*/std::nullopt,
DownloadWarningHatsProductSpecificData::GetBitsDataFields(
DownloadWarningHatsType::kDownloadBubbleBypass),
DownloadWarningHatsProductSpecificData::GetStringDataFields(
DownloadWarningHatsType::kDownloadBubbleBypass));
survey_configs.emplace_back(
&safe_browsing::kDownloadWarningSurvey,
kHatsSurveyTriggerDownloadWarningBubbleHeed,
/*presupplied_trigger_id=*/std::nullopt,
DownloadWarningHatsProductSpecificData::GetBitsDataFields(
DownloadWarningHatsType::kDownloadBubbleHeed),
DownloadWarningHatsProductSpecificData::GetStringDataFields(
DownloadWarningHatsType::kDownloadBubbleHeed));
survey_configs.emplace_back(
&safe_browsing::kDownloadWarningSurvey,
kHatsSurveyTriggerDownloadWarningBubbleIgnore,
/*presupplied_trigger_id=*/std::nullopt,
DownloadWarningHatsProductSpecificData::GetBitsDataFields(
DownloadWarningHatsType::kDownloadBubbleIgnore),
DownloadWarningHatsProductSpecificData::GetStringDataFields(
DownloadWarningHatsType::kDownloadBubbleIgnore));
survey_configs.emplace_back(
&safe_browsing::kDownloadWarningSurvey,
kHatsSurveyTriggerDownloadWarningPageBypass,
/*presupplied_trigger_id=*/std::nullopt,
DownloadWarningHatsProductSpecificData::GetBitsDataFields(
DownloadWarningHatsType::kDownloadsPageBypass),
DownloadWarningHatsProductSpecificData::GetStringDataFields(
DownloadWarningHatsType::kDownloadsPageBypass));
survey_configs.emplace_back(
&safe_browsing::kDownloadWarningSurvey,
kHatsSurveyTriggerDownloadWarningPageHeed,
/*presupplied_trigger_id=*/std::nullopt,
DownloadWarningHatsProductSpecificData::GetBitsDataFields(
DownloadWarningHatsType::kDownloadsPageHeed),
DownloadWarningHatsProductSpecificData::GetStringDataFields(
DownloadWarningHatsType::kDownloadsPageHeed));
survey_configs.emplace_back(
&safe_browsing::kDownloadWarningSurvey,
kHatsSurveyTriggerDownloadWarningPageIgnore,
/*presupplied_trigger_id=*/std::nullopt,
DownloadWarningHatsProductSpecificData::GetBitsDataFields(
DownloadWarningHatsType::kDownloadsPageIgnore),
DownloadWarningHatsProductSpecificData::GetStringDataFields(
DownloadWarningHatsType::kDownloadsPageIgnore));
survey_configs.emplace_back(
&features::kSafetyHubHaTSOneOffSurvey,
kHatsSurveyTriggerSafetyHubOneOffExperimentControl,
features::kHatsSurveyTriggerSafetyHubOneOffExperimentControlTriggerId
.Get());
survey_configs.emplace_back(
&features::kSafetyHubHaTSOneOffSurvey,
kHatsSurveyTriggerSafetyHubOneOffExperimentNotification,
features::kHatsSurveyTriggerSafetyHubOneOffExperimentNotificationTriggerId
.Get(),
sh_psd_fields);
survey_configs.emplace_back(
&features::kSafetyHubHaTSOneOffSurvey,
kHatsSurveyTriggerSafetyHubOneOffExperimentInteraction,
features::kHatsSurveyTriggerSafetyHubOneOffExperimentInteractionTriggerId
.Get(),
sh_psd_fields);
// Lens overlay surveys.
survey_configs.emplace_back(
&lens::features::kLensOverlaySurvey, kHatsSurveyTriggerLensOverlayResults,
/*presupplied_trigger_id=*/std::nullopt, std::vector<std::string>{},
std::vector<std::string>{"ID that's tied to your Google Lens session"});
// Merchant trust surveys
survey_configs.emplace_back(
&page_info::kMerchantTrustEvaluationControlSurvey,
kHatsSurveyTriggerMerchantTrustEvaluationControlSurvey);
survey_configs.emplace_back(
&page_info::kMerchantTrustEvaluationExperimentSurvey,
kHatsSurveyTriggerMerchantTrustEvaluationExperimentSurvey);
// The reason for this survey params being set here instead of in a finch
// config is that our MerchantTrust config has 2 HaTS surveys, one manually
// triggered and one pop-up (default HaTS behavior), and the finch config only
// supports one HaTS survey per study group. e.g. There can't be 2
// features with same param names within the same group, hence we need to set
// the one of the surveys params here.
hats::SurveyConfig merchant_trust_learn_survey_config(
&page_info::kMerchantTrustLearnSurvey,
kHatsSurveyTriggerMerchantTrustLearnSurvey,
page_info::kMerchantTrustLearnSurveyTriggerId.Get());
merchant_trust_learn_survey_config.user_prompted =
page_info::kMerchantTrustLearnSurveyUserPrompted.Get();
merchant_trust_learn_survey_config.probability =
page_info::kMerchantTrustLearnSurveyProbability.Get();
survey_configs.push_back(merchant_trust_learn_survey_config);
// Automated password change surveys.
survey_configs.emplace_back(
&password_manager::features::kImprovedPasswordChangeService,
kHatsSurveyTriggerPasswordChangeSuccess,
password_manager::features::kPasswordChangeSuccessSurveyTriggerId.Get(),
/*product_specific_bits_data_fields=*/
std::vector<std::string>{password_manager::features_util::
kPasswordChangeSuggestedPasswordsAdoption,
password_manager::features_util::
kPasswordChangeBlockingChallengeDetected},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
password_manager::features_util::
kPasswordChangeBreachedPasswordsCount,
password_manager::features_util::kPasswordChangeSavedPasswordsCount,
password_manager::features_util::kPasswordChangeRuntime});
survey_configs.emplace_back(
&password_manager::features::kImprovedPasswordChangeService,
kHatsSurveyTriggerPasswordChangeError,
password_manager::features::kPasswordChangeErrorSurveyTriggerId.Get(),
/*product_specific_bits_data_fields=*/
std::vector<std::string>{password_manager::features_util::
kPasswordChangeSuggestedPasswordsAdoption,
password_manager::features_util::
kPasswordChangeBlockingChallengeDetected},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
password_manager::features_util::
kPasswordChangeBreachedPasswordsCount,
password_manager::features_util::kPasswordChangeSavedPasswordsCount,
password_manager::features_util::kPasswordChangeRuntime});
survey_configs.emplace_back(
&password_manager::features::kImprovedPasswordChangeService,
kHatsSurveyTriggerPasswordChangeCanceled,
password_manager::features::kPasswordChangeCanceledSurveyTriggerId.Get(),
/*product_specific_bits_data_fields=*/
std::vector<std::string>{password_manager::features_util::
kPasswordChangeSuggestedPasswordsAdoption,
password_manager::features_util::
kPasswordChangeBlockingChallengeDetected},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
password_manager::features_util::
kPasswordChangeBreachedPasswordsCount,
password_manager::features_util::kPasswordChangeSavedPasswordsCount,
password_manager::features_util::kPasswordChangeRuntime});
survey_configs.emplace_back(
&password_manager::features::kImprovedPasswordChangeService,
kHatsSurveyTriggerPasswordChangeDelayed,
password_manager::features::kPasswordChangeDelayedSurveyTriggerId.Get(),
/*product_specific_bits_data_fields=*/
std::vector<std::string>{password_manager::features_util::
kPasswordChangeSuggestedPasswordsAdoption},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
password_manager::features_util::
kPasswordChangeBreachedPasswordsCount,
password_manager::features_util::kPasswordChangeSavedPasswordsCount});
#else
survey_configs.emplace_back(&chrome::android::kChromeSurveyNextAndroid,
kHatsSurveyTriggerAndroidStartupSurvey);
survey_configs.emplace_back(
&chrome::android::kQuickDeleteAndroidSurvey,
kHatsSurveyTriggerQuickDelete,
chrome::android::kQuickDeleteAndroidSurveyTriggerId.Get());
survey_configs.emplace_back(&chrome::android::kClearBrowsingDataAndroidSurvey,
kHatsSurveyTriggerClearBrowsingData);
std::vector<std::string> product_specific_bits_data_fields =
std::vector<std::string>{"Tapped card", "Has visited"};
std::vector<std::string> product_specific_string_data =
std::vector<std::string>{"Notification module type", "Global state"};
survey_configs.emplace_back(
&features::kSafetyHubAndroidSurvey, kHatsSurveyTriggerSafetyHubAndroid,
features::kSafetyHubAndroidTriggerId.Get(),
product_specific_bits_data_fields, product_specific_string_data);
survey_configs.emplace_back(&features::kSafetyHubAndroidOrganicSurvey,
kHatsSurveyOrganicTriggerSafetyHubAndroid,
features::kSafetyHubAndroidOrganicTriggerId.Get(),
product_specific_bits_data_fields,
product_specific_string_data);
#endif // #if !BUILDFLAG(IS_ANDROID)
survey_configs.emplace_back(
&autofill::features::kPlusAddressAcceptedFirstTimeCreateSurvey,
kHatsSurveyTriggerPlusAddressAcceptedFirstTimeCreate,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
plus_addresses::hats::kPlusAddressesCount,
plus_addresses::hats::kFirstPlusAddressCreationTime,
plus_addresses::hats::kLastPlusAddressFillingTime});
survey_configs.back().SetCooldownPeriodOverride(base::Days(
base::FeatureParam<int>(
&autofill::features::kPlusAddressAcceptedFirstTimeCreateSurvey,
plus_addresses::hats::kCooldownOverrideDays, 0)
.Get()));
survey_configs.emplace_back(
&autofill::features::kPlusAddressDeclinedFirstTimeCreateSurvey,
kHatsSurveyTriggerPlusAddressDeclinedFirstTimeCreate,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
plus_addresses::hats::kPlusAddressesCount,
plus_addresses::hats::kFirstPlusAddressCreationTime,
plus_addresses::hats::kLastPlusAddressFillingTime});
survey_configs.back().SetCooldownPeriodOverride(base::Days(
base::FeatureParam<int>(
&autofill::features::kPlusAddressDeclinedFirstTimeCreateSurvey,
plus_addresses::hats::kCooldownOverrideDays, 0)
.Get()));
survey_configs.emplace_back(
&autofill::features::kPlusAddressUserCreatedMultiplePlusAddressesSurvey,
kHatsSurveyTriggerPlusAddressCreatedMultiplePlusAddresses,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
plus_addresses::hats::kPlusAddressesCount,
plus_addresses::hats::kFirstPlusAddressCreationTime,
plus_addresses::hats::kLastPlusAddressFillingTime});
survey_configs.back().SetCooldownPeriodOverride(
base::Days(base::FeatureParam<int>(
&autofill::features::
kPlusAddressUserCreatedMultiplePlusAddressesSurvey,
plus_addresses::hats::kCooldownOverrideDays, 0)
.Get()));
survey_configs.emplace_back(
&autofill::features::
kPlusAddressUserCreatedPlusAddressViaManualFallbackSurvey,
kHatsSurveyTriggerPlusAddressCreatedPlusAddressViaManualFallback,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
plus_addresses::hats::kPlusAddressesCount,
plus_addresses::hats::kFirstPlusAddressCreationTime,
plus_addresses::hats::kLastPlusAddressFillingTime});
survey_configs.back().SetCooldownPeriodOverride(base::Days(
base::FeatureParam<int>(
&autofill::features::
kPlusAddressUserCreatedPlusAddressViaManualFallbackSurvey,
plus_addresses::hats::kCooldownOverrideDays, 0)
.Get()));
survey_configs.emplace_back(
&autofill::features::kPlusAddressUserDidChoosePlusAddressOverEmailSurvey,
kHatsSurveyTriggerPlusAddressDidChoosePlusAddressOverEmailSurvey,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
plus_addresses::hats::kPlusAddressesCount,
plus_addresses::hats::kFirstPlusAddressCreationTime,
plus_addresses::hats::kLastPlusAddressFillingTime});
survey_configs.back().SetCooldownPeriodOverride(
base::Days(base::FeatureParam<int>(
&autofill::features::
kPlusAddressUserDidChoosePlusAddressOverEmailSurvey,
plus_addresses::hats::kCooldownOverrideDays, 0)
.Get()));
survey_configs.emplace_back(
&autofill::features::kPlusAddressUserDidChooseEmailOverPlusAddressSurvey,
kHatsSurveyTriggerPlusAddressDidChooseEmailOverPlusAddressSurvey,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
plus_addresses::hats::kPlusAddressesCount,
plus_addresses::hats::kFirstPlusAddressCreationTime,
plus_addresses::hats::kLastPlusAddressFillingTime});
survey_configs.back().SetCooldownPeriodOverride(
base::Days(base::FeatureParam<int>(
&autofill::features::
kPlusAddressUserDidChooseEmailOverPlusAddressSurvey,
plus_addresses::hats::kCooldownOverrideDays, 0)
.Get()));
survey_configs.emplace_back(
&autofill::features::kPlusAddressFilledPlusAddressViaManualFallbackSurvey,
kHatsSurveyTriggerPlusAddressFilledPlusAddressViaManualFallback,
/*presupplied_trigger_id=*/std::nullopt,
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{
plus_addresses::hats::kPlusAddressesCount,
plus_addresses::hats::kFirstPlusAddressCreationTime,
plus_addresses::hats::kLastPlusAddressFillingTime});
survey_configs.back().SetCooldownPeriodOverride(
base::Days(base::FeatureParam<int>(
&autofill::features::
kPlusAddressFilledPlusAddressViaManualFallbackSurvey,
plus_addresses::hats::kCooldownOverrideDays, 0)
.Get()));
survey_configs.emplace_back(
&omnibox_feature_configs::HappinessTrackingSurveyForOmniboxOnFocusZps::
kHappinessTrackingSurveyForOmniboxOnFocusZps,
kHatsSurveyTriggerOnFocusZpsSuggestionsHappiness,
/*presupplied_trigger_id=*/"DzFWc1ACp0ugnJ3q1cK0RPxBRdLT",
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{"page classification", "channel"});
survey_configs.emplace_back(
&omnibox_feature_configs::HappinessTrackingSurveyForOmniboxOnFocusZps::
kHappinessTrackingSurveyForOmniboxOnFocusZps,
kHatsSurveyTriggerOnFocusZpsSuggestionsUtility,
/*presupplied_trigger_id=*/"7USxn1X280ugnJ3q1cK0P67JEQ7Y",
/*product_specific_bits_data_fields=*/std::vector<std::string>{},
/*product_specific_string_data_fields=*/
std::vector<std::string>{"page classification", "channel"});
return survey_configs;
}
} // namespace
namespace hats {
SurveyConfig::SurveyConfig() = default;
SurveyConfig::SurveyConfig(const SurveyConfig&) = default;
SurveyConfig::~SurveyConfig() = default;
SurveyConfig::SurveyConfig(
const base::Feature* feature,
const std::string& trigger,
const std::optional<std::string>& presupplied_trigger_id,
const std::vector<std::string>& product_specific_bits_data_fields,
const std::vector<std::string>& product_specific_string_data_fields,
bool log_responses_to_uma,
bool log_responses_to_ukm,
RequestedBrowserType requested_browser_type)
: trigger(trigger),
product_specific_bits_data_fields(product_specific_bits_data_fields),
product_specific_string_data_fields(product_specific_string_data_fields),
requested_browser_type(requested_browser_type),
survey_feature(feature) {
enabled = base::FeatureList::IsEnabled(*feature);
if (!enabled) {
return;
}
probability = base::FeatureParam<double>(feature, kHatsSurveyProbability,
kHatsSurveyProbabilityDefault)
.Get();
// The trigger_id may be provided through the associated feature parameter or
// may have been included in the source code. The latter is required to enable
// multiple surveys with a single finch group, as a limitation with finch
// prevents duplicate param names even for different features within a group.
// The feature parameter name is "en_site_id" for legacy reasons, as this
// was the HaTS v1 equivalent of a trigger ID in HaTS Next.
trigger_id = presupplied_trigger_id ? *presupplied_trigger_id
: base::FeatureParam<std::string>(
feature, kHatsSurveyEnSiteID, "")
.Get();
if (log_responses_to_uma) {
hats_histogram_name = ValidateHatsHistogramName(
base::FeatureParam<std::string>(feature, kHatsSurveyHistogramName, "")
.Get());
}
if (log_responses_to_ukm) {
hats_survey_ukm_id = ValidateHatsSurveyUkmId(
base::FeatureParam<int>(feature, kHatsSurveyUkmId, 0).Get());
}
user_prompted =
base::FeatureParam<bool>(feature, "user_prompted", false).Get();
}
// static
std::optional<std::string> SurveyConfig::ValidateHatsHistogramName(
const std::optional<std::string>& hats_histogram_name) {
return hats_histogram_name.has_value() &&
!hats_histogram_name.value().empty() &&
base::StartsWith(hats_histogram_name.value(),
kHatsHistogramPrefix)
? hats_histogram_name
: std::nullopt;
}
// static
std::optional<uint64_t> SurveyConfig::ValidateHatsSurveyUkmId(
const std::optional<uint64_t> hats_survey_ukm_id) {
return hats_survey_ukm_id.has_value() && hats_survey_ukm_id.value() > 0
? hats_survey_ukm_id
: std::nullopt;
}
void SurveyConfig::SetCooldownPeriodOverride(
const base::TimeDelta& cooldown_period_override) {
if (!cooldown_period_override.is_zero()) {
cooldown_period_override_ = cooldown_period_override;
}
}
std::optional<base::TimeDelta> SurveyConfig::GetCooldownPeriodOverride(
Profile* profile) const {
if (!cooldown_period_override_) {
return std::nullopt;
}
GoogleGroupsManager* groups_manager =
GoogleGroupsManagerFactory::GetForBrowserContext(profile);
if (!groups_manager) {
return std::nullopt;
}
if (!groups_manager->IsFeatureEnabledForProfile(*survey_feature) ||
!groups_manager->IsFeatureGroupControlled(*survey_feature)) {
return std::nullopt;
}
return cooldown_period_override_;
}
bool SurveyConfig::IsCooldownOverrideEnabled(Profile* profile) const {
return GetCooldownPeriodOverride(profile).has_value();
}
void GetActiveSurveyConfigs(SurveyConfigs& survey_configs_by_triggers_) {
auto surveys = GetAllSurveyConfigs();
// Filter down to active surveys configs and store them in a map for faster
// access. Triggers within the browser may attempt to show surveys regardless
// of whether the feature is enabled, so checking whether a particular survey
// is enabled should be fast.
for (const SurveyConfig& survey : surveys) {
if (!survey.enabled) {
continue;
}
survey_configs_by_triggers_.emplace(survey.trigger, survey);
}
}
} // namespace hats